package com.sc.nft.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.*;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.sc.nft.dao.*;
import com.sc.nft.dto.*;
import com.sc.nft.entity.*;
import com.sc.nft.entity.dto.*;
import com.sc.nft.entity.req.CollectionGiveDaoBatchRequest;
import com.sc.nft.entity.req.CollectionGiveDaoRequest;
import com.sc.nft.entity.vo.*;
import com.sc.nft.entity.vo.metaWalletDTO.MetaWalletCrossUserVO;
import com.sc.nft.enums.*;
import com.sc.nft.enums.wallet.DaoWalletTypeEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.feign.ChainFeignClient;
import com.sc.nft.helper.MessageQueueHelper;
import com.sc.nft.pool.UserPool;
import com.sc.nft.service.*;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.sup.Result;
import com.sc.nft.util.IdCardAuditUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户藏片表服务接口实现
 *
 * @author zxy
 * @description 由 Mybatisplus Code Generator 创建
 * @since 2022-06-04 01:42:17
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class UserCollectionServiceImpl implements UserCollectionService {
    private final UserCollectionDao userCollectionDao;
    private final UserInfoDao userInfoDao;
    private final StaticDataDao staticDataDao;
    private final IdcardInfoDao idcardInfoDao;
    private final DigitalCollectionDao digitalCollectionDao;
    private final PrivilegeService privilegeService;
    private final UserAssetsDao userAssetsDao;
    private final UserAssetsService userAssetsService;
    private final PrivilegeDao privilegeDao;
    private final ExitConsensusUserDao exitConsensusUserDao;
    private final UserCollectionConsensusDao userCollectionConsensusDao;
    private final ChainFeignClient chainFeignClient;
    private final UserChainAddrDao userChainAddrDao;
    private final UserCreatorInfoDao userCreatorInfoDao;
    private final CatenaInfoDao catenaInfoDao;
    private final DigitalCollectionProductInfoDao digitalCollectionProductInfoDao;
    private final OrderDao orderDao;
    private final DaoService daoService;
    private final SecondCollectionConfigDao secondCollectionConfigDao;
    private final SecondCollectionDao secondCollectionDao;
    private final SecondOrderDao secondOrderDao;
    private final UserChainInfoDao userChainInfoDao;
    private final UserCollectionChainLogDao userCollectionChainLogDao;
    private final CollectionChainInitDetailsLogService collectionChainInitDetailsLogService;
    private final MessageQueueHelper messageQueueHelper;
    private final CollectionChainInitDetailsLogDao collectionChainInitDetailsLogDao;
    private final ShowLevelDao showLevelDao;
    private final PackageRuleDao packageRuleDao;
    private final BoxEquityDao boxEquityDao;
    private final BoxProductDao boxProductDao;
    private final EquityPropsDao equityPropsDao;
    private final UserEquityPropsService userEquityPropsService;
    private final FilterIncomeListDao filterIncomeListDao;
    private final DaoIdentityDao daoIdentityDao;
    private final CollectionGiftDao collectionGiftDao;
    private final UserWalletService userWalletService;
    private final UserEcologyPointsService userEcologyPointsService;
    private final SecondEquityPropsOrderDao secondEquityPropsOrderDao;
    private final CollecionLinkContrastRecordsDao collecionLinkContrastRecordsDao;
    @Autowired
    private MetaWalletService metaWalletService;
    private final UserCityServerCentreDao usercityServiceCenterDao;
    private final UserConsensusService userConsensusService;
    private final CopyrightAuctionConfigDao copyrightAuctionConfigDao;
    private final CopyrightAuctionRecordDao copyrightAuctionRecordDao;
    private final CopyrightAuctionDao copyrightAuctionDao;
    private final NftRegionBindingService nftRegionBindingService;
    private final CollectiveOrderDao collectiveOrderDao;
    private final DaoWalletDao daoWalletDao;
    private final DaoWalletService daoWalletService;
    private final TempDaoUserCollectionHoldDao tempDaoUserCollectionHoldDao;
    private final TradingPoolOrderDao tradingPoolOrderDao;
    private final TradingRecycleLogDao tradingRecycleLogDao;
    private final ExportRecordsDao exportRecordsDao;
    private final OrderGasService orderGasService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserCollection addCollection(Long userId, Long giveUserId, Long collectionId, String collectionUuid, String collectionImage,
                                        CollectionLevel level, String firstTitle, Long userCreatorId, ReceivedCollectionType type, Long boxId,
                                        String boxTitle, String boxImage, Boolean isOpen, Long productId, Long orderId, Long secondOrderId,
                                        BigDecimal buyAmount, Integer numbering, Long fromUserCollectionId, String chainUrl, AddCollectionEnum addCollectionEnum, String fromUserAddress, String fromUserNickName, Boolean isDaoSource) {
        UserCollection userCollection = new UserCollection();
        userCollection.setNumbering(numbering);
        userCollection.setBoxId(boxId);
        userCollection.setBoxTitle(boxTitle);
        userCollection.setBoxImage(boxImage);
        userCollection.setIsOpen(isOpen);
        userCollection.setUserCreatorId(userCreatorId);
        userCollection.setCollectionId(collectionId);
        userCollection.setFromUserCollectionId(fromUserCollectionId);
        userCollection.setCollectionImage(collectionImage);
        userCollection.setFirstTitle(firstTitle);
        userCollection.setStatus(ChainStatusEnum.NONE);
        userCollection.setCollectionUuid(collectionUuid);
        userCollection.setGiveStatus(GiveStatusEnum.NOT);
        userCollection.setGiveUserId(giveUserId);
        userCollection.setUserId(userId);
        userCollection.setType(type);
        userCollection.setLevel(level);
        userCollection.setProductId(productId);
        userCollection.setOrderId(orderId);
        userCollection.setSecondOrderId(secondOrderId);
        userCollection.setIsHold(true);
        userCollection.setOnConsign(CollectionOnConsignEnum.NORMAL);
        userCollection.setBuyPrice(buyAmount);//这个价格只用商品的价格
        userCollection.setAntiHoardFlag(false);
        userCollection.setChainUrl(chainUrl);
        //24-07-03 与翔宇确认逻辑调整
        // 品牌孵化所有藏品默认防囤
        // 自由不用,只有品牌孵化的防囤价才有意义
        Integer hoardSeqNo = 0;
        DigitalCollection collection = digitalCollectionDao.getById(userCollection.getCollectionId());
        SecondCollectionConfig secondCollectionConfig = secondCollectionConfigDao.getByCollectionId(collection.getId());
        if (ObjectUtil.isNotNull(secondCollectionConfig) && secondCollectionConfig.getMarketType() == MarketTypeEnum.BRAND_INCUBATION && ObjectUtil.isNotNull(collection.getAntiHoardCount())) {
            hoardSeqNo = collection.getAntiHoardCount();
            userCollection.setAntiHoardFlag(Boolean.TRUE);
            userCollection.setAntiHoardPrice(userCollection.getBuyPrice().add(userCollection.getBuyPrice().multiply(collection.getAntiHoardRatio())));
        } else {
            userCollection.setAntiHoardFlag(Boolean.FALSE);
            hoardSeqNo = 0;
        }
        userCollection.setHoardSeqNo(hoardSeqNo);

//        userCollection.setHoardSeqNo(userCollectionDao.getNotHoardCountByCollectionId(userCollection.getCollectionId(), userCollection.getUserId()) + 1);
//        if (collection.getAntiHoardCount() != null && collection.getAntiHoardCount() > -1 && userCollection.getHoardSeqNo() > collection.getAntiHoardCount()) {
//            userCollection.setAntiHoardFlag(Boolean.TRUE);
//            userCollection.setAntiHoardPrice(userCollection.getBuyPrice().add(userCollection.getBuyPrice().multiply(collection.getAntiHoardRatio())));
//        } else {
//            userCollection.setAntiHoardFlag(Boolean.FALSE);
//        }
        userCollection.setCollectionType(collection.getCollectionType());

        Boolean isSmeltingOnly = Boolean.FALSE;
        if (!Lists.newArrayList(ReceivedCollectionType.TRANSFER_FROM_META_WALLET, ReceivedCollectionType.CONSIGN).contains(type)) {
            DigitalCollectionProductInfo digitalCollectionProductInfo = digitalCollectionProductInfoDao.getById(productId);
            if (BeanUtil.isNotEmpty(digitalCollectionProductInfo)) {
                isSmeltingOnly = digitalCollectionProductInfo.getIsSmeltingOnly();
            }
        }
        if (filterIncomeListDao.getIsContainsUserId(giveUserId) && collection.getCollectionType() == DigitalMarketTypeEnum.ECOLOGY
                && type == ReceivedCollectionType.RECEIVED && BooleanUtil.isFalse(isDaoSource)) {
            isSmeltingOnly = true;
        }
        userCollection.setIsSmeltingOnly(isSmeltingOnly);
        // 锁仓操作.这个很重要.修改时候请务必读对应代码,他影响着所有用户藏品的锁仓时间一级是否锁仓操作
        FilterIncomeList filterIncomeList = filterIncomeListDao.getByUserId(userId);
        // 市值账号购买,不进行锁仓
        if (BeanUtil.isNotEmpty(filterIncomeList)) {
            addCollectionEnum = AddCollectionEnum.DEFAULT;
        }
        lockUserCollection(collectionId, productId, addCollectionEnum, userCollection);
        userCollection.insert();
        privilegeService.flushUserLevel(userId);

        //如果不是盲盒
        if (userCollection.getIsOpen()) {
            //升级逻辑
            daoService.upgrade(collectionId, userId, type);
        }

        StaticData activityBoxIdString = staticDataDao.getByType("activity_box_id");
        if (ObjectUtil.isNotNull(activityBoxIdString)) {
            Long activityBoxId = Long.valueOf(activityBoxIdString.getValue());
            if (productId.longValue() == activityBoxId.longValue()) {
                StaticData activityEquityPropsId = staticDataDao.getByType("activity_equity_props_id");
                if (ObjectUtil.isNotNull(activityEquityPropsId)) {
                    EquityProps equityProps = equityPropsDao.getById(Long.valueOf(activityEquityPropsId.getValue()));
                    userEquityPropsService.addEquityPropsByUser(equityProps, userId, UserEquityPropsGetTypeEnum.ACTIVITY, 1,
                            boxTitle, productId, BigDecimal.ZERO, UserEquityPropsGetTypeEnum.ACTIVITY, productId);
                }
            }
        }

        String contractAddress = StrUtil.EMPTY;
        //查询链上代执行记录
        //1.判断是否是盲盒  如果不是盲盒才是要插入
        //2.所有的都是交易
        if (userCollection.getIsOpen()) {
            //如果不是盲盒 才要插入
            UserCollectionChainLog userCollectionChainLog = new UserCollectionChainLog();
            userCollectionChainLog.setUserId(userCollection.getUserId());
            userCollectionChainLog.setDaoId(0L);
            userCollectionChainLog.setUserCollectionId(userCollection.getId());
            userCollectionChainLog.setCollectionType(userCollection.getType());
            userCollectionChainLog.setType(UserChainTypeEnum.TRANSFER);
            userCollectionChainLog.setStatus(UserChainLogStatusEnum.WAIT);
            userCollectionChainLog.setCollectionId(userCollection.getCollectionId());
            userCollectionChainLog.setContractAddress(collection.getContractAddress());
            userCollectionChainLog.setProductId(userCollection.getCollectionUuid());

            if (ObjectUtil.isNotEmpty(giveUserId)) {

                if (type != ReceivedCollectionType.TRANSFER_FROM_META_WALLET) {
                    //是否是转增
                    //如果是转增 则是转增的获取现在的fromuser的链信息
                    userCollectionChainLog.setFromUserId(giveUserId);
                    UserChainInfo fromUserChainInfo = userChainInfoDao.getRegisterByUserId(giveUserId);
                    userCollectionChainLog.setFromUserAddress(fromUserChainInfo.getAddress());
                    //fromUser藏品链信息
                    UserCollectionChainLog userCollectionChain = userCollectionChainLogDao.getOneByUserIdAndUserCollectionId(giveUserId, fromUserCollectionId);
                    if (ObjectUtil.isNull(userCollectionChain)) {
                        throw new GlobalRunTimeException("持有藏品链上信息错误");
                    }
                    userCollectionChainLog.setDeployTransactionHash(userCollectionChain.getDeployTransactionHash());
                    userCollectionChainLog.setContractAddress(userCollectionChain.getContractAddress());
                    userCollectionChainLog.setTokenId(userCollectionChain.getTokenId());
                    userCollectionChainLog.setCollectionChainId(userCollectionChain.getCollectionChainId());
                    userCollectionChainLog.setFromUserAddress(fromUserChainInfo.getAddress());
                    userCollectionChainLog.setFromUserCollectionId(userCollectionChain.getUserCollectionId());
                    userCollectionChain.setFromUserId(giveUserId);
                } else { //跨链转增

                    userCollectionChainLog.setFromUserId(0L);
                    UserChainInfo fromUserChainInfo = userChainInfoDao.getRegisterByUserId(1L);
                    userCollectionChainLog.setFromUserAddress(fromUserChainInfo.getAddress());

                    CollectionChainInitDetailsLog chainInitDetailsLog = collectionChainInitDetailsLogDao.getOneByCollectionIdAnTokenIdAndStatsAndDealStatus(collectionId, numbering, UserChainLogStatusEnum.SUCCESS);
                    userCollectionChainLog.setType(UserChainTypeEnum.FROM_META_WALLET);
                    userCollectionChainLog.setDeployTransactionHash(chainInitDetailsLog.getDeployTransactionHash());
                    userCollectionChainLog.setContractAddress(chainInitDetailsLog.getContractAddress());
                    userCollectionChainLog.setTokenId(chainInitDetailsLog.getTokenId());
                    userCollectionChainLog.setCollectionChainId(chainInitDetailsLog.getId());
                    userCollectionChainLog.setFromUserAddress(fromUserAddress);
                    userCollectionChainLog.setFromUserCollectionId(0L);
                    contractAddress = chainInitDetailsLog.getContractAddress();

                    //更细仓库藏品链记录
                    Assert.isTrue(collectionChainInitDetailsLogDao.updateDealStatusById(chainInitDetailsLog.getId(), CollectionChainDealStatusEnum.TRADEDING), () -> new GlobalRunTimeException("更新链上藏品状态失败"));
                }


            } else {
                //不是转增 则是交易
                //交易的话 分配新的链上藏品
                UserChainInfo userChain = userChainInfoDao.getRegisterByUserId(1L);
                userCollectionChainLog.setFromUserId(userChain.getUserId());
                userCollectionChainLog.setFromUserCollectionId(0L);
                userCollectionChainLog.setFromUserAddress(userChain.getAddress());

                //获取最近一条可以交易的链上藏品
                CollectionChainInitDetailsLog chainInitDetailsLog = collectionChainInitDetailsLogService.getCanTransfer(userCollection.getCollectionId());
                userCollectionChainLog.setCollectionChainId(chainInitDetailsLog.getId());
                userCollectionChainLog.setTokenId(chainInitDetailsLog.getTokenId());
                userCollectionChainLog.setDeployTransactionHash(chainInitDetailsLog.getDeployTransactionHash());
                userCollectionChainLog.setProductId(chainInitDetailsLog.getCollectionUuid());
                userCollection.setNumbering(chainInitDetailsLog.getNumbering());
                //更细仓库藏品链记录
                Assert.isTrue(collectionChainInitDetailsLogDao.updateDealStatusById(chainInitDetailsLog.getId(), CollectionChainDealStatusEnum.TRADEDING), () -> new GlobalRunTimeException("更新链上藏品状态失败"));

                //更新用户藏品表id与
                Assert.isTrue(userCollectionDao.updateUuIdAndNumberingById(userCollection.getId(), chainInitDetailsLog.getCollectionUuid(), chainInitDetailsLog.getNumbering()), () -> new GlobalRunTimeException("更新uuid失败"));
            }

            userCollectionChainLog.setToUserId(userCollection.getUserId());
            userCollectionChainLog.setToUserCollectionId(userCollection.getId());

            UserChainInfo userChainInfo = userChainInfoDao.getRegisterByUserId(userCollection.getUserId());
            if (ObjectUtil.isNull(userChainInfo)) {
                throw new GlobalRunTimeException("链地址生成中,请稍后再试");
            }
            userCollectionChainLog.setToUserAddress(userChainInfo.getAddress());
            userCollectionChainLog.insert();

            if (type == ReceivedCollectionType.TRANSFER_FROM_META_WALLET) {
                TransferCollectionWithoutRecords transferCollectionWithoutRecords = new TransferCollectionWithoutRecords();
                transferCollectionWithoutRecords.setTransferType(TransferCollectionWithoutTypeEnum.RECEIVE);
                transferCollectionWithoutRecords.setType(CollectionOriginalTypeEnum.MATE_UNIVERSE);
                transferCollectionWithoutRecords.setUserId(userId);
                transferCollectionWithoutRecords.setUserCollectionId(userCollection.getUserId());
                transferCollectionWithoutRecords.setCollectionId(userCollection.getCollectionId());
                transferCollectionWithoutRecords.setTokenId(numbering);
                transferCollectionWithoutRecords.setToUserAddr(userChainInfo.getAddress());
                transferCollectionWithoutRecords.setFromUserAddr(fromUserAddress);
                transferCollectionWithoutRecords.setStatus(TransferCollectionWithoutStatusEnum.EXECUTING);
                transferCollectionWithoutRecords.setContractAddress(contractAddress);
                transferCollectionWithoutRecords.setUserCollectionChainLogId(userCollectionChainLog.getId());
                transferCollectionWithoutRecords.setFromUserNickName(fromUserNickName);
                transferCollectionWithoutRecords.insert();
            }

        }

        //region 上链费分红，目前只有寄售订单或集售订单涉及，且市值账号购买不参与上链费分红
        OrderGasShareDTO orderGasShareDTO = new OrderGasShareDTO();
        if (ObjectUtil.isNull(filterIncomeList) && Objects.nonNull(secondOrderId)) {
            //寄售
            if (Objects.equals(ReceivedCollectionType.CONSIGN, type)) {
                SecondOrder secondOrder = secondOrderDao.getById(secondOrderId);
                if (Objects.nonNull(secondOrder)
                        && Objects.nonNull(secondOrder.getGas())
                        && secondOrder.getGas().compareTo(BigDecimal.ZERO) > 0) {
                    orderGasShareDTO.setCollectionId(collectionId);
                    orderGasShareDTO.setGas(secondOrder.getGas());
                    orderGasShareDTO.setOrderId(secondOrderId);
                    orderGasShareDTO.setOrderNo(secondOrder.getOrderNo());
                    orderGasShareDTO.setOrderType(OrderGasTypeEnum.CONSIGN);
                    orderGasShareDTO.setOrderTime(DateTime.now());
                }
            }
            //集售
            if (Objects.equals(ReceivedCollectionType.COLLECTIVE, type)) {
                CollectiveOrder collectiveOrder = collectiveOrderDao.getById(secondOrderId);
                if (Objects.nonNull(collectiveOrder)
                        && Objects.nonNull(collectiveOrder.getGas())
                        && collectiveOrder.getGas().compareTo(BigDecimal.ZERO) > 0) {
                    orderGasShareDTO.setCollectionId(collectionId);
                    orderGasShareDTO.setGas(collectiveOrder.getGas());
                    orderGasShareDTO.setOrderId(secondOrderId);
                    orderGasShareDTO.setOrderNo(collectiveOrder.getOrderNo());
                    orderGasShareDTO.setOrderType(OrderGasTypeEnum.COLLECTIVE);
                    orderGasShareDTO.setOrderTime(DateTime.now());
                }
            }
            //交易池
            if (Objects.equals(ReceivedCollectionType.TRADING_POOL, type)) {
                TradingPoolOrder tradingPoolOrder = tradingPoolOrderDao.getById(secondOrderId);
                if (Objects.nonNull(tradingPoolOrder)
                        && Objects.nonNull(tradingPoolOrder.getGas())
                        && tradingPoolOrder.getGas().compareTo(BigDecimal.ZERO) > 0) {
                    orderGasShareDTO.setCollectionId(collectionId);
                    orderGasShareDTO.setGas(tradingPoolOrder.getGas());
                    orderGasShareDTO.setOrderId(secondOrderId);
                    orderGasShareDTO.setOrderNo(tradingPoolOrder.getOrderNo());
                    orderGasShareDTO.setOrderType(OrderGasTypeEnum.TRADING_POOL);
                    orderGasShareDTO.setOrderTime(DateTime.now());
                }
            }
        }
        //endregion

        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCommit() {
                //购买的时候发送
                if (ReceivedCollectionType.BUY.getCode() == type.getCode() || ReceivedCollectionType.CONSIGN.getCode() == type.getCode() || ReceivedCollectionType.ROUGH_STONE.getCode() == type.getCode()) {
                    SaasTaskBurialPointDTO saasTaskBurialPointDTO = new SaasTaskBurialPointDTO();
                    messageQueueHelper.sendMessage(MessageTopic.DISK_TAKER, saasTaskBurialPointDTO.wallet(userId, SaasTaskTypeEnum.PURCHASE_OF_DESIGNATED_COLLECTION, BigDecimal.ONE, 1, collectionId), SaasTaskTypeEnum.PURCHASE_OF_DESIGNATED_COLLECTION.name());
                    messageQueueHelper.sendMessage(MessageTopic.DISK_TAKER, saasTaskBurialPointDTO.wallet(userId, SaasTaskTypeEnum.INVITATION_TO_PURCHASE_SPECIFIED_COLLECTIONS, BigDecimal.ONE, 1, collectionId), SaasTaskTypeEnum.INVITATION_TO_PURCHASE_SPECIFIED_COLLECTIONS.name());
                    // 支付成功后.发送任务判定 新用户首次购买
                    messageQueueHelper.sendMessage(MessageTopic.DISK_TAKER, saasTaskBurialPointDTO.wallet(userId, SaasTaskTypeEnum.NEW_USERS_MAKE_THEIR_FIRST_PURCHASE, Convert.toBigDecimal(1), 0, collectionId), SaasTaskTypeEnum.NEW_USERS_MAKE_THEIR_FIRST_PURCHASE.name());
                    // 支付成功后.发送任务判定 邀请新用户首次购买
                    messageQueueHelper.sendMessage(MessageTopic.DISK_TAKER, saasTaskBurialPointDTO.wallet(userId, SaasTaskTypeEnum.INVITE_NEW_USERS_TO_MAKE_THEIR_FIRST_PURCHASE, Convert.toBigDecimal(1), 0, collectionId), SaasTaskTypeEnum.INVITE_NEW_USERS_TO_MAKE_THEIR_FIRST_PURCHASE.name());
                }
                // CDK兑换
                if (ReceivedCollectionType.EXCHANGECDK.getCode() == type.getCode()) {
                    SaasTaskBurialPointDTO saasTaskBurialPointDTO = new SaasTaskBurialPointDTO();
                    messageQueueHelper.sendMessage(MessageTopic.DISK_TAKER, saasTaskBurialPointDTO.wallet(userId, SaasTaskTypeEnum.CDK_REDEMPTION_TASK, BigDecimal.ONE, 1, collectionId), SaasTaskTypeEnum.CDK_REDEMPTION_TASK.name());
                }
                // 合成
                if (ReceivedCollectionType.SYNTHESIS.getCode() == type.getCode()) {
                    SaasTaskBurialPointDTO saasTaskBurialPointDTO = new SaasTaskBurialPointDTO();
                    messageQueueHelper.sendMessage(MessageTopic.DISK_TAKER, saasTaskBurialPointDTO.wallet(userId, SaasTaskTypeEnum.COMPOSITE_COLLECTION, BigDecimal.ONE, 1, collectionId), SaasTaskTypeEnum.COMPOSITE_COLLECTION.name());
                }

                // 1级首发购买
                if (ReceivedCollectionType.BUY.getCode() == type.getCode()) {
                    SaasTaskBurialPointDTO saasTaskBurialPointDTO = new SaasTaskBurialPointDTO();
                    messageQueueHelper.sendMessage(MessageTopic.DISK_TAKER, saasTaskBurialPointDTO.wallet(userId, SaasTaskTypeEnum.PURCHASE_PLATFORM_DEBUT_ANY_COLLECTION, buyAmount, 1, collectionId, orderId), SaasTaskTypeEnum.PURCHASE_PLATFORM_DEBUT_ANY_COLLECTION.name());
                    // 消费额度
                    messageQueueHelper.sendMessage(MessageTopic.DISK_TAKER, saasTaskBurialPointDTO.wallet(userId, SaasTaskTypeEnum.ACCUMULATED_CONSUMPTION_AMOUNT, buyAmount, 0, collectionId, orderId, SaasTaskMeetConditionsLocationEnum.COLLECTION), SaasTaskTypeEnum.ACCUMULATED_CONSUMPTION_AMOUNT.name());

                }

                // 2级购买
                if (ReceivedCollectionType.CONSIGN.getCode() == type.getCode()) {
                    SaasTaskBurialPointDTO saasTaskBurialPointDTO = new SaasTaskBurialPointDTO();
                    messageQueueHelper.sendMessage(MessageTopic.DISK_TAKER, saasTaskBurialPointDTO.wallet(userId, SaasTaskTypeEnum.FREE_MARKET_PURCHASE_OF_ANY_COLLECTION, buyAmount, 1, collectionId, orderId), SaasTaskTypeEnum.FREE_MARKET_PURCHASE_OF_ANY_COLLECTION.name());
                    messageQueueHelper.sendMessage(MessageTopic.DISK_TAKER, saasTaskBurialPointDTO.wallet(userId, SaasTaskTypeEnum.BUY_BRAND_HATCHING_ANY_COLLECTION, buyAmount, 1, collectionId, orderId), SaasTaskTypeEnum.BUY_BRAND_HATCHING_ANY_COLLECTION.name());
                }

                //上链费分红
                if (Objects.nonNull(orderGasShareDTO.getOrderId())) {
                    messageQueueHelper.sendMessage(MessageTopic.ORDER_GAS_SHARE, orderGasShareDTO, MessageTopic.ORDER_GAS_SHARE, orderGasShareDTO.getOrderNo());
                }
            }
        });

        return userCollection;
    }


    @Override
    public IPage<MallCollectionUserVO> pageUserIdByCollectionId(MallCollectionUSerDTO mallCollectionUSerDTO) {
        return userCollectionDao.pageUserListByCollectionIds(new Page<>(mallCollectionUSerDTO.getPageNo(), mallCollectionUSerDTO.getPageSize()), mallCollectionUSerDTO.getCollectionIds());
    }

    @Override
    public IPage<MallUserCollectionVO> pageMallUserCollection(MallUserCollectionDTO mallUserCollectionDTO) {
        Page<MallUserCollectionVO> mallUserCollectionVOPage = userCollectionDao.pageMallUserCollection(mallUserCollectionDTO);
        if (CollectionUtils.isEmpty(mallUserCollectionVOPage.getRecords())) {
            return mallUserCollectionVOPage;
        }

        List<Long> ids = mallUserCollectionVOPage.getRecords().stream().map(MallUserCollectionVO::getCollectionId).collect(Collectors.toList());
        List<DigitalCollection> digitalCollections = digitalCollectionDao.listByIds(ids);
        Map<Long, DigitalCollection> digitalCollectionMap = digitalCollections.stream().collect(Collectors.toMap(DigitalCollection::getId, digitalCollection -> digitalCollection));

        for (MallUserCollectionVO record : mallUserCollectionVOPage.getRecords()) {
            DigitalCollection digitalCollection = digitalCollectionMap.get(record.getCollectionId());
            if (Objects.nonNull(digitalCollection)) {
                record.setCollectionImage(digitalCollection.getCreationContent());
            }
        }

        return mallUserCollectionVOPage;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserCollection addCollectionForExchange(Long userId, Long giveUserId, Long collectionId, String
            collectionUuid, String collectionImage,
                                                   CollectionLevel level, String firstTitle, Long userCreatorId, ReceivedCollectionType type, Long boxId,
                                                   String boxTitle, String boxImage, Boolean isOpen, Long productId, Long orderId, Long secondOrderId,
                                                   BigDecimal buyAmount, Integer numbering, Long fromUserCollectionId, String chainUrl, AddCollectionEnum
                                                           addCollectionEnum, Long id) {
        UserCollection userCollection = new UserCollection();
        userCollection.setNumbering(numbering);
        userCollection.setBoxId(boxId);
        userCollection.setBoxTitle(boxTitle);
        userCollection.setBoxImage(boxImage);
        userCollection.setIsOpen(isOpen);
        userCollection.setUserCreatorId(userCreatorId);
        userCollection.setCollectionId(collectionId);
        userCollection.setFromUserCollectionId(fromUserCollectionId);
        userCollection.setCollectionImage(collectionImage);
        userCollection.setFirstTitle(firstTitle);
        userCollection.setStatus(ChainStatusEnum.NONE);
        userCollection.setCollectionUuid(collectionUuid);
        userCollection.setGiveStatus(GiveStatusEnum.NOT);
        userCollection.setGiveUserId(giveUserId);
        userCollection.setUserId(userId);
        userCollection.setType(type);
        userCollection.setLevel(level);
        userCollection.setProductId(productId);
        userCollection.setOrderId(orderId);
        userCollection.setSecondOrderId(secondOrderId);
        userCollection.setIsHold(true);
        userCollection.setOnConsign(CollectionOnConsignEnum.NORMAL);
        userCollection.setBuyPrice(buyAmount);//这个价格只用商品的价格
        userCollection.setAntiHoardFlag(false);
        userCollection.setChainUrl(chainUrl);
        userCollection.setTaskPoolId(id);
        //24-07-03 与翔宇确认逻辑调整
        // 品牌孵化所有藏品默认防囤
        // 自由不用,只有品牌孵化的防囤价才有意义
        Integer hoardSeqNo = 0;
        DigitalCollection collection = digitalCollectionDao.getById(userCollection.getCollectionId());
        SecondCollectionConfig secondCollectionConfig = secondCollectionConfigDao.getByCollectionId(collection.getId());
        if (ObjectUtil.isNotNull(secondCollectionConfig) && secondCollectionConfig.getMarketType() == MarketTypeEnum.BRAND_INCUBATION && ObjectUtil.isNotNull(collection.getAntiHoardCount())) {
            hoardSeqNo = collection.getAntiHoardCount();
            userCollection.setAntiHoardFlag(Boolean.TRUE);
            userCollection.setAntiHoardPrice(userCollection.getBuyPrice().add(userCollection.getBuyPrice().multiply(collection.getAntiHoardRatio())));
        } else {
            userCollection.setAntiHoardFlag(Boolean.FALSE);
            hoardSeqNo = 0;
        }
        userCollection.setHoardSeqNo(hoardSeqNo);

//        userCollection.setHoardSeqNo(userCollectionDao.getNotHoardCountByCollectionId(userCollection.getCollectionId(), userCollection.getUserId()) + 1);
//        if (collection.getAntiHoardCount() != null && collection.getAntiHoardCount() > -1 && userCollection.getHoardSeqNo() > collection.getAntiHoardCount()) {
//            userCollection.setAntiHoardFlag(Boolean.TRUE);
//            userCollection.setAntiHoardPrice(userCollection.getBuyPrice().add(userCollection.getBuyPrice().multiply(collection.getAntiHoardRatio())));
//        } else {
//            userCollection.setAntiHoardFlag(Boolean.FALSE);
//        }
        userCollection.setCollectionType(collection.getCollectionType());
        DigitalCollectionProductInfo digitalCollectionProductInfo = digitalCollectionProductInfoDao.getById(productId);
        if (BeanUtil.isEmpty(digitalCollectionProductInfo)) {
            throw new GlobalRunTimeException("商品不存在");
        }
        userCollection.setIsSmeltingOnly(digitalCollectionProductInfo.getIsSmeltingOnly());
        // 锁仓操作.这个很重要.修改时候请务必读对应代码,他影响着所有用户藏品的锁仓时间一级是否锁仓操作
        FilterIncomeList filterIncomeList = filterIncomeListDao.getByUserId(userId);
        // 市值账号购买,不进行锁仓
        if (BeanUtil.isNotEmpty(filterIncomeList)) {
            addCollectionEnum = AddCollectionEnum.DEFAULT;
        }
        lockUserCollection(collectionId, productId, addCollectionEnum, userCollection);
        userCollection.insert();
        privilegeService.flushUserLevel(userId);

        //如果不是盲盒
        if (userCollection.getIsOpen()) {
            //升级逻辑
            daoService.upgrade(collectionId, userId, type);
        }

        StaticData activityBoxIdString = staticDataDao.getByType("activity_box_id");
        if (ObjectUtil.isNotNull(activityBoxIdString)) {
            Long activityBoxId = Long.valueOf(activityBoxIdString.getValue());
            if (productId.longValue() == activityBoxId.longValue()) {
                StaticData activityEquityPropsId = staticDataDao.getByType("activity_equity_props_id");
                if (ObjectUtil.isNotNull(activityEquityPropsId)) {
                    EquityProps equityProps = equityPropsDao.getById(Long.valueOf(activityEquityPropsId.getValue()));
                    userEquityPropsService.addEquityPropsByUser(equityProps, userId, UserEquityPropsGetTypeEnum.ACTIVITY, 1, boxTitle, productId,
                            BigDecimal.ZERO, UserEquityPropsGetTypeEnum.ACTIVITY, productId);
                }
            }
        }


        //查询链上代执行记录
        //1.判断是否是盲盒  如果不是盲盒才是要插入
        //2.所有的都是交易
        if (userCollection.getIsOpen()) {
            //如果不是盲盒 才要插入
            UserCollectionChainLog userCollectionChainLog = new UserCollectionChainLog();
            userCollectionChainLog.setUserId(userCollection.getUserId());
            userCollectionChainLog.setDaoId(0L);
            userCollectionChainLog.setUserCollectionId(userCollection.getId());
            userCollectionChainLog.setCollectionType(userCollection.getType());
            userCollectionChainLog.setType(UserChainTypeEnum.TRANSFER);
            userCollectionChainLog.setStatus(UserChainLogStatusEnum.WAIT);
            userCollectionChainLog.setCollectionId(userCollection.getCollectionId());
            userCollectionChainLog.setContractAddress(collection.getContractAddress());
            userCollectionChainLog.setProductId(userCollection.getCollectionUuid());

            if (ObjectUtil.isNotEmpty(giveUserId)) {
                //是否是转增
                //如果是转增 则是转增的获取现在的fromuser的链信息
                userCollectionChainLog.setFromUserId(giveUserId);
                UserChainInfo fromUserChainInfo = userChainInfoDao.getRegisterByUserId(giveUserId);
                userCollectionChainLog.setFromUserAddress(fromUserChainInfo.getAddress());
                //fromUser藏品链信息
                UserCollectionChainLog userCollectionChain = userCollectionChainLogDao.getOneByUserIdAndUserCollectionId(giveUserId, fromUserCollectionId);
                if (ObjectUtil.isNull(userCollectionChain)) {
                    throw new GlobalRunTimeException("持有藏品链上信息错误");
                }
                userCollectionChainLog.setDeployTransactionHash(userCollectionChain.getDeployTransactionHash());
                userCollectionChainLog.setContractAddress(userCollectionChain.getContractAddress());
                userCollectionChainLog.setTokenId(userCollectionChain.getTokenId());
                userCollectionChainLog.setCollectionChainId(userCollectionChain.getCollectionChainId());
                userCollectionChainLog.setFromUserAddress(fromUserChainInfo.getAddress());
                userCollectionChainLog.setFromUserCollectionId(userCollectionChain.getUserCollectionId());
                userCollectionChain.setFromUserId(giveUserId);
            } else {
                //不是转增 则是交易
                //交易的话 分配新的链上藏品
                UserChainInfo userChain = userChainInfoDao.getRegisterByUserId(1L);
                userCollectionChainLog.setFromUserId(userChain.getUserId());
                userCollectionChainLog.setFromUserCollectionId(0L);
                userCollectionChainLog.setFromUserAddress(userChain.getAddress());

                //获取最近一条可以交易的链上藏品
                CollectionChainInitDetailsLog chainInitDetailsLog = collectionChainInitDetailsLogService.getCanTransfer(userCollection.getCollectionId());
                userCollectionChainLog.setCollectionChainId(chainInitDetailsLog.getId());
                userCollectionChainLog.setTokenId(chainInitDetailsLog.getTokenId());
                userCollectionChainLog.setDeployTransactionHash(chainInitDetailsLog.getDeployTransactionHash());
                userCollectionChainLog.setProductId(chainInitDetailsLog.getCollectionUuid());
                //更细仓库藏品链记录
                Assert.isTrue(collectionChainInitDetailsLogDao.updateDealStatusById(chainInitDetailsLog.getId(), CollectionChainDealStatusEnum.TRADEDING), () -> new GlobalRunTimeException("更新链上藏品状态失败"));

                //更新用户藏品表id与
                Assert.isTrue(userCollectionDao.updateUuIdAndNumberingById(userCollection.getId(), chainInitDetailsLog.getCollectionUuid(), chainInitDetailsLog.getNumbering()), () -> new GlobalRunTimeException("更新uuid失败"));
            }

            userCollectionChainLog.setToUserId(userCollection.getUserId());
            userCollectionChainLog.setToUserCollectionId(userCollection.getId());

            UserChainInfo userChainInfo = userChainInfoDao.getRegisterByUserId(userCollection.getUserId());
            if (ObjectUtil.isNull(userChainInfo)) {
                throw new GlobalRunTimeException("链地址生成中,请稍后再试");
            }
            userCollectionChainLog.setToUserAddress(userChainInfo.getAddress());
            userCollectionChainLog.insert();
        }


        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCommit() {
                //购买的时候发送
                if (ReceivedCollectionType.BUY.getCode() == type.getCode() || ReceivedCollectionType.CONSIGN.getCode() == type.getCode() || ReceivedCollectionType.ROUGH_STONE.getCode() == type.getCode()) {
                    SaasTaskBurialPointDTO saasTaskBurialPointDTO = new SaasTaskBurialPointDTO();
                    messageQueueHelper.sendMessage(MessageTopic.DISK_TAKER, saasTaskBurialPointDTO.wallet(userId, SaasTaskTypeEnum.PURCHASE_OF_DESIGNATED_COLLECTION, BigDecimal.ONE, 1, collectionId), SaasTaskTypeEnum.PURCHASE_OF_DESIGNATED_COLLECTION.name());
                    messageQueueHelper.sendMessage(MessageTopic.DISK_TAKER, saasTaskBurialPointDTO.wallet(userId, SaasTaskTypeEnum.INVITATION_TO_PURCHASE_SPECIFIED_COLLECTIONS, BigDecimal.ONE, 1, collectionId), SaasTaskTypeEnum.INVITATION_TO_PURCHASE_SPECIFIED_COLLECTIONS.name());
                    // 支付成功后.发送任务判定 新用户首次购买
                    messageQueueHelper.sendMessage(MessageTopic.DISK_TAKER, saasTaskBurialPointDTO.wallet(userId, SaasTaskTypeEnum.NEW_USERS_MAKE_THEIR_FIRST_PURCHASE, Convert.toBigDecimal(1), 0, collectionId), SaasTaskTypeEnum.NEW_USERS_MAKE_THEIR_FIRST_PURCHASE.name());
                    // 支付成功后.发送任务判定 邀请新用户首次购买
                    messageQueueHelper.sendMessage(MessageTopic.DISK_TAKER, saasTaskBurialPointDTO.wallet(userId, SaasTaskTypeEnum.INVITE_NEW_USERS_TO_MAKE_THEIR_FIRST_PURCHASE, Convert.toBigDecimal(1), 0, collectionId), SaasTaskTypeEnum.INVITE_NEW_USERS_TO_MAKE_THEIR_FIRST_PURCHASE.name());
                }
                // CDK兑换
                if (ReceivedCollectionType.EXCHANGECDK.getCode() == type.getCode()) {
                    SaasTaskBurialPointDTO saasTaskBurialPointDTO = new SaasTaskBurialPointDTO();
                    messageQueueHelper.sendMessage(MessageTopic.DISK_TAKER, saasTaskBurialPointDTO.wallet(userId, SaasTaskTypeEnum.CDK_REDEMPTION_TASK, BigDecimal.ONE, 1, collectionId), SaasTaskTypeEnum.CDK_REDEMPTION_TASK.name());
                }
                // 合成
                if (ReceivedCollectionType.SYNTHESIS.getCode() == type.getCode()) {
                    SaasTaskBurialPointDTO saasTaskBurialPointDTO = new SaasTaskBurialPointDTO();
                    messageQueueHelper.sendMessage(MessageTopic.DISK_TAKER, saasTaskBurialPointDTO.wallet(userId, SaasTaskTypeEnum.COMPOSITE_COLLECTION, BigDecimal.ONE, 1, collectionId), SaasTaskTypeEnum.COMPOSITE_COLLECTION.name());
                }

                // 1级首发购买
                if (ReceivedCollectionType.BUY.getCode() == type.getCode()) {
                    SaasTaskBurialPointDTO saasTaskBurialPointDTO = new SaasTaskBurialPointDTO();
                    messageQueueHelper.sendMessage(MessageTopic.DISK_TAKER, saasTaskBurialPointDTO.wallet(userId, SaasTaskTypeEnum.PURCHASE_PLATFORM_DEBUT_ANY_COLLECTION, buyAmount, 1, collectionId, orderId), SaasTaskTypeEnum.PURCHASE_PLATFORM_DEBUT_ANY_COLLECTION.name());
                    // 消费额度
                    messageQueueHelper.sendMessage(MessageTopic.DISK_TAKER, saasTaskBurialPointDTO.wallet(userId, SaasTaskTypeEnum.ACCUMULATED_CONSUMPTION_AMOUNT, buyAmount, 0, collectionId, orderId, SaasTaskMeetConditionsLocationEnum.COLLECTION), SaasTaskTypeEnum.ACCUMULATED_CONSUMPTION_AMOUNT.name());

                }

                // 2级购买
                if (ReceivedCollectionType.CONSIGN.getCode() == type.getCode()) {
                    SaasTaskBurialPointDTO saasTaskBurialPointDTO = new SaasTaskBurialPointDTO();
                    messageQueueHelper.sendMessage(MessageTopic.DISK_TAKER, saasTaskBurialPointDTO.wallet(userId, SaasTaskTypeEnum.FREE_MARKET_PURCHASE_OF_ANY_COLLECTION, buyAmount, 1, collectionId, orderId), SaasTaskTypeEnum.FREE_MARKET_PURCHASE_OF_ANY_COLLECTION.name());
                    messageQueueHelper.sendMessage(MessageTopic.DISK_TAKER, saasTaskBurialPointDTO.wallet(userId, SaasTaskTypeEnum.BUY_BRAND_HATCHING_ANY_COLLECTION, buyAmount, 1, collectionId, orderId), SaasTaskTypeEnum.BUY_BRAND_HATCHING_ANY_COLLECTION.name());
                }
            }
        });

        return userCollection;
    }

    private void lockUserCollection(Long collectionId, Long productId, AddCollectionEnum
            addCollectionEnum, UserCollection userCollection) {
        // 处理锁仓时间
        // 一级锁仓
        if (addCollectionEnum == AddCollectionEnum.STAIR) {
            // 获取对应的商品信息
            DigitalCollectionProductInfo digitalCollectionProductInfo = digitalCollectionProductInfoDao.getById(productId);
            if (!digitalCollectionProductInfo.getIsLockedPosition()) {
                // 没有锁仓,直接赋予当前时间
                userCollection.setLockedPositionTime(DateUtil.date());
            }
            if (digitalCollectionProductInfo.getIsLockedPosition()) {
                if (digitalCollectionProductInfo.getLockedPositionType().equals(1)) {
                    // 时间模式.向后偏移对应的小时数
                    userCollection.setLockedPositionTime(DateUtil.offsetHour(DateUtil.date(), digitalCollectionProductInfo.getLockedPositionHour()));
                }
                if (digitalCollectionProductInfo.getLockedPositionType().equals(2)) {
                    // 日期模式,指定时间释放掉全部锁仓.
                    userCollection.setLockedPositionTime(digitalCollectionProductInfo.getLockedPositionTime());
                }
            }
        }

        // 二级锁仓,使用二级订单配置进行锁仓判定
        if (addCollectionEnum == AddCollectionEnum.SECOND) {
            // 获取对应的商品信息
            SecondCollectionConfig secondCollectionConfig = secondCollectionConfigDao.getByCollectionId(collectionId);
            if (!secondCollectionConfig.getIsLockedPosition()) {
                // 没有锁仓,直接赋予当前时间
                userCollection.setLockedPositionTime(DateUtil.date());
            }
            if (secondCollectionConfig.getIsLockedPosition()) {
                if (secondCollectionConfig.getLockedPositionType().equals(1)) {
                    // 时间模式.向后偏移对应的小时数
                    userCollection.setLockedPositionTime(DateUtil.offsetHour(DateUtil.date(), secondCollectionConfig.getLockedPositionHour()));
                }
                if (secondCollectionConfig.getLockedPositionType().equals(2)) {
                    // 日期模式,指定时间释放掉全部锁仓.
                    userCollection.setLockedPositionTime(secondCollectionConfig.getLockedPositionTime());
                }
            }
        }
        // 默认,给当前获取时间就可以.不设置锁仓延期等操作
        if (addCollectionEnum == AddCollectionEnum.DEFAULT||addCollectionEnum == AddCollectionEnum.TRADING_POOL||addCollectionEnum == AddCollectionEnum.COLLECTIVE) {
            userCollection.setLockedPositionTime(DateUtil.date());
        }
    }

    @Override
    public Page<MyCollectionNowVO> myCollectionNow(String isPrivilege, Long userId, int pageNo, int pageSize) {
        if (ObjectUtil.isEmpty(isPrivilege)) {
            isPrivilege = "0";
        }
        UserInfo user = UserPool.getUser();
        //苹果审核处理 特定账号不能寄售
        Boolean isIosShow = Boolean.TRUE;
        if (user.getUserTel().equals("13849904109")) {
            isIosShow = Boolean.FALSE;
        }

        Page<MyCollectionNowVO> page = userCollectionDao.myCollectionNow(isPrivilege, userId, pageNo, pageSize);
        page.getRecords().forEach(myCollectionNowVO -> {
            // 循环获取dao名字，dao的图片 藏品品质
            UserCreatorInfo byIdCash = userCreatorInfoDao.getByIdCash(myCollectionNowVO.getUserCreatorId());
            if (BeanUtil.isNotEmpty(byIdCash)) {
                myCollectionNowVO.setUserCreatorName(byIdCash.getDaoName());
                myCollectionNowVO.setUserCreatorImg(byIdCash.getCreatorAvatarImg());
            }
            ShowLevel byShowLevelCash = showLevelDao.getByShowLevelCash(myCollectionNowVO.getShowLevel());
            if (BeanUtil.isNotEmpty(byShowLevelCash)) {
                myCollectionNowVO.setShowLevelName(byShowLevelCash.getShowLevelName());
            }
        });
        if (isIosShow) {
            return page;
        } else {
            List<MyCollectionNowVO> records = page.getRecords();
            ArrayList<MyCollectionNowVO> objectArrayList = Lists.newArrayList();
            for (MyCollectionNowVO record : records) {
                record.setConsignmentSales(0);
                objectArrayList.add(record);
            }
            page.setRecords(objectArrayList);
            return page;
        }
    }

    @Override
    public Page<MyCollectionVO> myCollection(String isPrivilege, Long userId, int pageNo, int pageSize) {
        if (ObjectUtil.isEmpty(isPrivilege)) {
            isPrivilege = "0";
        }
        Page<MyCollectionVO> myCollectionVOPage = userCollectionDao.myCollection(isPrivilege, userId, pageNo, pageSize);
        List<MyCollectionVO> records = myCollectionVOPage.getRecords();
        for (MyCollectionVO record : records) {
            if (record.getIsGive()) {
                DigitalCollection digitalCollection = digitalCollectionDao.getById(record.getCollectionId());
                UserCollection userCollection = userCollectionDao.getById(record.getId());
                Date createTime = userCollection.getCreateTime();
                if (ObjectUtil.isEmpty(createTime)) {
                    createTime = userCollection.getModifyTime();
                }
                if (ObjectUtil.isNotEmpty(createTime)) {
                    DateTime dateTime = DateUtil.offsetDay(createTime, digitalCollection.getLockupDays());
                    if (DateTime.now().before(dateTime)) {
                        record.setIsGive(Boolean.FALSE);
                    }
                }
            }
        }
        return myCollectionVOPage;
    }

    @Override
    public Page<MyBoxVO> myBox(Long userId, GiveStatusEnum giveStatus, int pageNo, int pageSize) {
        if (giveStatus.getCode() == GiveStatusEnum.NOT.getCode()) {

            return userCollectionDao.myBox(userId, giveStatus, pageNo, pageSize);
        } else {

            return userCollectionDao.myBoxByGiveStatus(userId, giveStatus, pageNo, pageSize);
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void give(UserInfo userInfo, String toUserUUID, Long userCollectionId) {

        UserCollection userCollection = userCollectionDao.getById(userCollectionId);

        if (!userInfo.getIsValid()) {
            throw new GlobalRunTimeException(ErrorCode.IF_YOU_HAVA_NOT_BECOME_A_VALID_USER_YOU_CANNOT_TRANSFER);
        }


        // 锁仓中
        if (userCollection.getLockedPositionTime() != null && userCollection.getLockedPositionTime().after(DateUtil.date())) {
            throw new GlobalRunTimeException(ErrorCode.LOCK_COLLECTION);
        }


        UserChainInfo fromUserChain = userChainInfoDao.getByUserId(userInfo.getId());
        UserChainInfo byAddress = userChainInfoDao.getByAddress(toUserUUID);
        if (ObjectUtil.isNull(byAddress)) {
            throw new GlobalRunTimeException(ErrorCode.THE_TARGET_USER_DOES_NOT_EXIST);
        }

        if (fromUserChain.getUserId().longValue() == byAddress.getUserId().longValue()) {
            throw new GlobalRunTimeException(ErrorCode.THE_TARGET_USER_CANNOT_BE_YOURSELF);
        }
        verifyCollection(userCollection, userInfo);
        if (!userCollection.getIsOpen() && userCollection.getStatus() == ChainStatusEnum.NONE) {
            userCollection.setStatus(ChainStatusEnum.ONLINE);
        }

        if (userCollection.getStatus() != ChainStatusEnum.ONLINE) {
            throw new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_ONLINE);
        }
        // 需要确定他是不是盲盒,如果是盲盒的话要单独做判定
        if (!userCollection.getIsOpen() && userCollection.getBoxId() != null && userCollection.getBoxId() != 0L) {
            BoxProduct boxProduct = boxProductDao.getById(userCollection.getBoxId());
            if (ObjectUtil.isEmpty(boxProduct)) {
                throw new GlobalRunTimeException(ErrorCode.MALL_PRODUCT_DOES_NOT_EXIST);
            }
            if (!boxProduct.getIsGive()) {
                throw new GlobalRunTimeException(ErrorCode.THIS_COLLECTION_CANNOT_BE_TRANSFERRED);
            }
        }


//        List<Long> list = giveBlackListDao.getEnableList();
//        if(list.contains(userCollection.getCollectionId())){
//            throw new GlobalRunTimeException(ErrorCode.THIS_COLLECTION_CANNOT_BE_TRANSFERRED);
//        }

        BigDecimal giveFeeString = new BigDecimal(staticDataDao.getByType("give_fee").getValue());
        if (userInfo.getPrivilegeLevel() != null && userInfo.getPrivilegeLevel() > 0) {
            Privilege privilege = privilegeDao.getByLevel(userInfo.getPrivilegeLevel());
            if (privilege.getTransferDiscount().compareTo(BigDecimal.ZERO) > 0) {
                giveFeeString = giveFeeString.multiply(privilege.getTransferDiscount());
            }
        }

        UserAssets userAssets = userAssetsDao.getByUserIdAndCoinId(userInfo.getId(), CoinCategoryEnum.INTEGRAL.getCode());
        BigDecimal tokenNum = userAssets.getTokenNum();

        if (tokenNum.compareTo(giveFeeString) == -1) {
            throw new GlobalRunTimeException(ErrorCode.YOU_CURRENTLY_HAVE_INSUFFICIENT_POINTS_AVAILBALE);
        }
        //扣积分
        Boolean aBoolean = userAssetsService.subIntegralByUserId(giveFeeString, userInfo.getId(), CoinCategoryEnum.INTEGRAL, AssetChangeLogEnum.SUB_GIVE_FEE, userCollection.getId(), AssetChangeLogEnum.SUB_GIVE_FEE.getName());
        if (!aBoolean) {
            throw new GlobalRunTimeException(ErrorCode.THE_SYSTEM_IS_BUSY_PLEASE_TRY_AGAIN_LATER);
        }

        UserChainInfo userChainInfo = userChainInfoDao.getByAddr(toUserUUID);
        Assert.notNull(userChainInfo, () -> new GlobalRunTimeException(ErrorCode.USER_ADDRESS_IS_BEING_GENERATED));

        UserInfo toUser = userInfoDao.getByUUID(userChainInfo.getUserUuid());
        Assert.notNull(toUser, () -> new GlobalRunTimeException(ErrorCode.THE_USER_DOES_NOT_EXIST));
        Assert.isFalse(toUser.getIsFreeze(), () -> new GlobalRunTimeException(ErrorCode.THE_USER_DOES_NOT_EXIST));
        Assert.isTrue(toUser.getIsSm(), () -> new GlobalRunTimeException(ErrorCode.USER_NOT_SM));

        userCollection.setGiveStatus(GiveStatusEnum.GIVING);
        userCollection.setGiveTime(DateTime.now());
        userCollection.setIsHold(false);
        userCollection.setToUserId(toUser.getId());
        if (!userCollection.updateById()) {
            throw new GlobalRunTimeException(ErrorCode.THE_SYSTEM_IS_BUSY_PLEASE_TRY_AGAIN_LATER);
        }
        privilegeService.flushUserLevel(userCollection.getUserId());

        //降级逻辑
        daoService.downgrade(userCollection.getCollectionId(), userCollection.getUserId(), ReceivedCollectionType.GIVE);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void buy(SecondOrder secondOrder) {

        UserCollection userCollection = userCollectionDao.getById(secondOrder.getUserCollectionId());
        if (ObjectUtil.isEmpty(userCollection)) {
            throw new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND);
        }
        if (userCollection.getUserId().longValue() != secondOrder.getSalesUserId().longValue()) {
            throw new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND);
        }
        if (!userCollection.getIsHold()) {
            throw new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND);
        }

        if ((Objects.isNull(secondOrder.getIsSecondWantBuyOrder()) || !secondOrder.getIsSecondWantBuyOrder()) && userCollection.getOnConsign() != CollectionOnConsignEnum.ON_SALES) {
            throw new GlobalRunTimeException(ErrorCode.NOT_CON_SIGN);
        }

        userCollection.setGiveTime(DateTime.now());
        userCollection.setIsHold(false);
        userCollection.setToUserId(secondOrder.getBuyUserId());
        if (!userCollection.updateById()) {
            throw new GlobalRunTimeException(ErrorCode.THE_SYSTEM_IS_BUSY_PLEASE_TRY_AGAIN_LATER);
        }
        privilegeService.flushUserLevel(userCollection.getUserId());
        //降级逻辑
        daoService.downgrade(userCollection.getCollectionId(), userCollection.getUserId(), ReceivedCollectionType.GIVE);
        UserCollection buyUserCollection = addCollection(secondOrder.getBuyUserId(), secondOrder.getSalesUserId(), userCollection.getCollectionId(),
                userCollection.getCollectionUuid(), userCollection.getCollectionImage(), userCollection.getLevel(), userCollection.getFirstTitle(),
                userCollection.getUserCreatorId(), ReceivedCollectionType.CONSIGN, userCollection.getBoxId(), userCollection.getBoxTitle(),
                userCollection.getBoxImage(), userCollection.getIsOpen(), userCollection.getProductId(), userCollection.getOrderId(), secondOrder.getId(), secondOrder.getBuyPrice(), userCollection.getNumbering(), userCollection.getId(), userCollection.getChainUrl(), AddCollectionEnum.SECOND, null, null, false);

        //藏品流转表记录
        CollectionCirculatingRecord collectionCirculatingRecord = new CollectionCirculatingRecord();
        collectionCirculatingRecord.setUserId(secondOrder.getBuyUserId());
        collectionCirculatingRecord.setCollectionId(userCollection.getCollectionId());
        collectionCirculatingRecord.setReceivedCollectionType(ReceivedCollectionType.CONSIGN);
        if (ObjectUtil.isEmpty(userCollection.getBoxId())) {
            collectionCirculatingRecord.setTypeClassify(ClassifyType.COLLECTION);
        } else {
            collectionCirculatingRecord.setTypeClassify(ClassifyType.BLIND_BOX);
        }
        collectionCirculatingRecord.setToUserCollection(buyUserCollection.getId());
        collectionCirculatingRecord.setToUserId(buyUserCollection.getUserId());
        collectionCirculatingRecord.setFromUserId(userCollection.getUserId());
        collectionCirculatingRecord.setFromUserCollection(userCollection.getId());
        collectionCirculatingRecord.insert();

        CollectionCirculatingRecord fromCollectionCirculatingRecord = new CollectionCirculatingRecord();
        fromCollectionCirculatingRecord.setUserId(secondOrder.getSalesUserId());
        fromCollectionCirculatingRecord.setCollectionId(userCollection.getCollectionId());
        fromCollectionCirculatingRecord.setReceivedCollectionType(ReceivedCollectionType.CONSIGN);
        if (ObjectUtil.isEmpty(userCollection.getBoxId())) {
            fromCollectionCirculatingRecord.setTypeClassify(ClassifyType.COLLECTION);
        } else {
            fromCollectionCirculatingRecord.setTypeClassify(ClassifyType.BLIND_BOX);
        }
        fromCollectionCirculatingRecord.setToUserCollection(buyUserCollection.getId());
        fromCollectionCirculatingRecord.setToUserId(buyUserCollection.getUserId());
        fromCollectionCirculatingRecord.setFromUserId(userCollection.getUserId());
        fromCollectionCirculatingRecord.setFromUserCollection(userCollection.getId());
        fromCollectionCirculatingRecord.insert();

    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void buyCollective(CollectiveOrder collectiveOrder) {

        UserCollection userCollection = userCollectionDao.getById(collectiveOrder.getUserCollectionId());
        if (ObjectUtil.isEmpty(userCollection)) {
            throw new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND);
        }
        if (userCollection.getUserId().longValue() != collectiveOrder.getSalesUserId().longValue()) {
            throw new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND);
        }
        if (!userCollection.getIsHold()) {
            throw new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND);
        }

        if (userCollection.getOnConsign() != CollectionOnConsignEnum.ON_COLLECTIVE) {
            throw new GlobalRunTimeException("该藏品已撤销集售");
        }

        userCollection.setGiveTime(DateTime.now());
        userCollection.setIsHold(false);
        userCollection.setToUserId(collectiveOrder.getBuyUserId());
        if (!userCollection.updateById()) {
            throw new GlobalRunTimeException(ErrorCode.THE_SYSTEM_IS_BUSY_PLEASE_TRY_AGAIN_LATER);
        }
        privilegeService.flushUserLevel(userCollection.getUserId());
        //降级逻辑
        daoService.downgrade(userCollection.getCollectionId(), userCollection.getUserId(), ReceivedCollectionType.GIVE);
        UserCollection buyUserCollection = addCollection(collectiveOrder.getBuyUserId(), collectiveOrder.getSalesUserId(), userCollection.getCollectionId(),
                userCollection.getCollectionUuid(), userCollection.getCollectionImage(), userCollection.getLevel(), userCollection.getFirstTitle(),
                userCollection.getUserCreatorId(), ReceivedCollectionType.COLLECTIVE, userCollection.getBoxId(), userCollection.getBoxTitle(),
                userCollection.getBoxImage(), userCollection.getIsOpen(), userCollection.getProductId(), userCollection.getOrderId(), collectiveOrder.getId(), collectiveOrder.getBuyPrice(), userCollection.getNumbering(), userCollection.getId(), userCollection.getChainUrl(), AddCollectionEnum.COLLECTIVE, null, null, false);

        //藏品流转表记录
        CollectionCirculatingRecord collectionCirculatingRecord = new CollectionCirculatingRecord();
        collectionCirculatingRecord.setUserId(collectiveOrder.getBuyUserId());
        collectionCirculatingRecord.setCollectionId(userCollection.getCollectionId());
        collectionCirculatingRecord.setReceivedCollectionType(ReceivedCollectionType.COLLECTIVE);
        if (ObjectUtil.isEmpty(userCollection.getBoxId())) {
            collectionCirculatingRecord.setTypeClassify(ClassifyType.COLLECTION);
        } else {
            collectionCirculatingRecord.setTypeClassify(ClassifyType.BLIND_BOX);
        }
        collectionCirculatingRecord.setToUserCollection(buyUserCollection.getId());
        collectionCirculatingRecord.setToUserId(buyUserCollection.getUserId());
        collectionCirculatingRecord.setFromUserId(userCollection.getUserId());
        collectionCirculatingRecord.setFromUserCollection(userCollection.getId());
        collectionCirculatingRecord.insert();

        CollectionCirculatingRecord fromCollectionCirculatingRecord = new CollectionCirculatingRecord();
        fromCollectionCirculatingRecord.setUserId(collectiveOrder.getSalesUserId());
        fromCollectionCirculatingRecord.setCollectionId(userCollection.getCollectionId());
        fromCollectionCirculatingRecord.setReceivedCollectionType(ReceivedCollectionType.CONSIGN);
        if (ObjectUtil.isEmpty(userCollection.getBoxId())) {
            fromCollectionCirculatingRecord.setTypeClassify(ClassifyType.COLLECTION);
        } else {
            fromCollectionCirculatingRecord.setTypeClassify(ClassifyType.BLIND_BOX);
        }
        fromCollectionCirculatingRecord.setToUserCollection(buyUserCollection.getId());
        fromCollectionCirculatingRecord.setToUserId(buyUserCollection.getUserId());
        fromCollectionCirculatingRecord.setFromUserId(userCollection.getUserId());
        fromCollectionCirculatingRecord.setFromUserCollection(userCollection.getId());
        fromCollectionCirculatingRecord.insert();

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserCollection openBox(UserInfo userInfo, Long userCollectionId) {
        UserCollection userCollection = userCollectionDao.getLastNotOpenBox(userInfo.getId(), userCollectionId);
        Assert.notNull(userCollection, () -> new GlobalRunTimeException("当前没有未开启的盲盒"));
        verifyOperBox(userCollection, userInfo);
        userCollection.setIsOpen(true);
        if (!userCollection.updateById()) {
            throw new GlobalRunTimeException(ErrorCode.THE_SYSTEM_IS_BUSY_PLEASE_TRY_AGAIN_LATER);
        }
        privilegeService.flushUserLevel(userCollection.getUserId());
        if (ObjectUtil.isNotNull(digitalCollectionDao.getEcologyCollectionById(userCollection.getCollectionId()))) {
            userConsensusService.adjustConsensusService(userInfo.getId(), userCollection.getCollectionId(), BigDecimal.ONE, UserConsensusTypeEnums.OPEN_BOX, userCollection.getFirstTitle(), null);
        }
        //发放盲盒奖励
        if (ObjectUtil.isNotNull(userCollection.getBoxId())) {
            BoxProduct boxProduct = boxProductDao.getById(userCollection.getBoxId());
            List<BoxEquity> boxEquityList = boxEquityDao.getByBoxIdAndCollectionId(userCollection.getBoxId(), userCollection.getCollectionId());
            boxEquityList.stream().forEach(b -> {
                //星球积分
                if (BoxEquityTypeEnum.POINTS.getCode() == b.getLinkType().intValue()) {
                    userAssetsService.addIntegralByUserId(b.getLinkCount(), userInfo.getId(), CoinCategoryEnum.INTEGRAL, AssetChangeLogEnum.BOX_AWARD, b.getId(), "开启：" + boxProduct.getFirstTitle());
                }
                //权益道具
                else {
                    EquityProps equityProps = equityPropsDao.getById(b.getLinkId());
                    userEquityPropsService.addEquityPropsByUser(equityProps, userInfo.getId(), UserEquityPropsGetTypeEnum.BOX_AWARD, b.getLinkCount().intValue(), "开启：" + boxProduct.getFirstTitle(),
                            userCollection.getId(), BigDecimal.ZERO, UserEquityPropsGetTypeEnum.BOX_AWARD, userCollection.getId());
                }
            });
        }

        UserCollectionChainLog query = userCollectionChainLogDao.getOneByUserIdAndUserCollectionId(userCollection.getUserId(), userCollection.getId());
        if (ObjectUtil.isNull(query)) {
            //执行链上操作
            UserCollectionChainLog userCollectionChainLog = new UserCollectionChainLog();
            userCollectionChainLog.setUserId(userInfo.getId());
            userCollectionChainLog.setUserCollectionId(userCollection.getId());
            userCollectionChainLog.setCollectionType(userCollection.getType());
            userCollectionChainLog.setCollectionId(userCollection.getCollectionId());


            UserChainInfo userChain = userChainInfoDao.getRegisterByUserId(1L);
            userCollectionChainLog.setFromUserAddress(userChain.getAddress());
            userCollectionChainLog.setFromUserCollectionId(0l);

            userCollectionChainLog.setToUserId(userInfo.getId());
            userCollectionChainLog.setToUserCollectionId(userCollection.getId());
            UserChainInfo userChainInfo = userChainInfoDao.getRegisterByUserId(userCollection.getUserId());
            if (ObjectUtil.isNull(userChainInfo)) {
                throw new GlobalRunTimeException("用户未注册链上账户");
            }
            userCollectionChainLog.setToUserAddress(userChainInfo.getAddress());
            userCollectionChainLog.setStatus(UserChainLogStatusEnum.WAIT);
            userCollectionChainLog.setType(UserChainTypeEnum.MINT);
            UserChainInfo initUserChain = userChainInfoDao.getById(1L);
            userCollectionChainLog.setFromUserId(1L);
            userCollectionChainLog.setFromUserAddress(initUserChain.getAddress());
            //获取最近一条可以交易的链上藏品
            CollectionChainInitDetailsLog chainInitDetailsLog = collectionChainInitDetailsLogService.getCanTransfer(userCollection.getCollectionId());

            userCollectionChainLog.setTokenId(chainInitDetailsLog.getTokenId());
            userCollectionChainLog.setType(UserChainTypeEnum.TRANSFER);
            userCollectionChainLog.setCollectionChainId(chainInitDetailsLog.getId());
            userCollectionChainLog.setContractAddress(chainInitDetailsLog.getContractAddress());
            userCollectionChainLog.setDeployTransactionHash(chainInitDetailsLog.getDeployTransactionHash());
            userCollectionChainLog.setTokenId(chainInitDetailsLog.getTokenId());
            userCollectionChainLog.setProductId(chainInitDetailsLog.getCollectionUuid());
            //更细仓库藏品链记录
            Assert.isTrue(collectionChainInitDetailsLogDao.updateDealStatusById(chainInitDetailsLog.getId(), CollectionChainDealStatusEnum.TRADEDING), () -> new GlobalRunTimeException("更新链上藏品状态失败"));
            //更新用户藏品记录
            Assert.isTrue(userCollectionDao.updateUuIdAndNumberingById(userCollection.getId(), chainInitDetailsLog.getCollectionUuid(), chainInitDetailsLog.getNumbering()), () -> new GlobalRunTimeException("更新藏品编号失败"));
            userCollectionChainLog.insert();
        }

        return userCollection;
    }

    /**
     * 获取随机的盲盒
     *
     * @param list
     * @return
     */
    private CollectionChainInitDetailsLog getCollectionChainInitDetailsLogByList
    (List<CollectionChainInitDetailsLog> list, Long productId) {

        /**
         *  2888在卖掉4000以后出现，前面开盲盒的数字还是要随机的
         */
        //打算顺序
        Collections.shuffle(list);
        //获取第一个
        CollectionChainInitDetailsLog userCollectionChainLog = list.get(0);
        if (userCollectionChainLog.getNumbering().intValue() == 2888 && productId.intValue() == 509) {
            //判断已商品售出数量
            Integer sellCount = orderDao.getCountByProductId(productId);
            if (sellCount < 4000) {
                if (list.size() == 1) {//如果长度只有1个 那就是最后一个
                    userCollectionChainLog = list.get(0);
                } else {
                    userCollectionChainLog = list.get(1);
                }
            }
        }
        return userCollectionChainLog;
    }

    @Override
    public Page<CollectionLogDTO> giveCollectionLog(UserInfo userInfo, int pageNo, int pageSize) {
        return userCollectionDao.giveCollectionLog(userInfo.getId(), pageNo, pageSize);
    }

    @Override
    public Page<CollectionLogDTO> getCollectionLog(UserInfo userInfo, int pageNo, int pageSize) {
        return userCollectionDao.getCollectionLog(userInfo.getId(), pageNo, pageSize);
    }

    @Override
    public GiveDetailsVO giveDetails(UserInfo user, Long id) {
        UserCollection userCollection = userCollectionDao.getById(id);
        if (ObjectUtil.isEmpty(userCollection)) {
            throw new GlobalRunTimeException(ErrorCode.PARAM_ERROR);
        }

        if (!userCollection.getIsHold()) {
            throw new GlobalRunTimeException(ErrorCode.PARAM_ERROR);
        }

//        List<Long> list = giveBlackListDao.getEnableList();
//        if (list.contains(userCollection.getCollectionId())) {
//            throw new GlobalRunTimeException(ErrorCode.THIS_COLLECTION_CANNOT_BE_TRANSFERRED);
//        }
        GiveDetailsVO giveDetailsVO = new GiveDetailsVO();
        UserAssets userAssets = userAssetsDao.getByUserIdAndCoinId(user.getId(), CoinCategoryEnum.INTEGRAL.getCode());
        String giveFeeString = staticDataDao.getByType("give_fee").getValue();
        if (user.getPrivilegeLevel() != null && user.getPrivilegeLevel() > 0) {
            Privilege privilege = privilegeDao.getByLevel(user.getPrivilegeLevel());
            if (privilege.getTransferDiscount().compareTo(BigDecimal.ZERO) > 0) {
                giveFeeString = new BigDecimal(giveFeeString).multiply(privilege.getTransferDiscount()).stripTrailingZeros().toPlainString();
            }
        }
        BigDecimal tokenNum = userAssets.getTokenNum();

        giveDetailsVO.setGiveFee(giveFeeString);
        giveDetailsVO.setUserIntegralNum(tokenNum.stripTrailingZeros().toPlainString());
        giveDetailsVO.setMsg("");
        if (tokenNum.compareTo(new BigDecimal(giveFeeString)) == -1) {
            giveDetailsVO.setMsg("您可用积分不足");
        }
        if (userCollection.getIsOpen()) {
            String collectionImage = userCollection.getCollectionImage();
            String firstTitle = userCollection.getFirstTitle();
            giveDetailsVO.setFirstTitle(firstTitle);
            giveDetailsVO.setCreationContent(collectionImage);
        } else {
            String boxImage = userCollection.getBoxImage();
            String boxTitle = userCollection.getBoxTitle();
            giveDetailsVO.setFirstTitle(boxTitle);
            giveDetailsVO.setCreationContent(boxImage);
        }

        giveDetailsVO.setId(id);
        String transferRules = staticDataDao.getByType("transfer_rules").getValue();
        String giveFaceIsClose = staticDataDao.getByType("give_face_is_close").getValue();
        giveDetailsVO.setTransferRules(transferRules);
        Boolean isTransferCheckFace = user.getIsTransferCheckFace();
        if (ObjectUtil.isNotEmpty(giveFaceIsClose) && "0".equals(giveFaceIsClose)) {
            isTransferCheckFace = true;
        }

        //设置商品主图
        DigitalCollectionProductInfo product = digitalCollectionProductInfoDao.getById(userCollection.getProductId());
        giveDetailsVO.setProductDetailPicture(userCollection.getIsOpen() ? userCollection.getCollectionImage() : userCollection.getBoxImage());
        giveDetailsVO.setProductDetailPictureType(product.getProductDetailPictureType());
        giveDetailsVO.setModelImg(product.getModelImg());
        giveDetailsVO.setModelDistance(product.getModelDistance());
        giveDetailsVO.setFlag(!isTransferCheckFace);
        return giveDetailsVO;
    }

    @Override
    public List<NotOpenBlindBoxVO> notOpenBlindBox(Long boxId) {
        return userCollectionDao.notOpenBlindBox(UserPool.getUser().getId(), boxId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editGiveStatus(UserCollection userCollection) {
        userCollection.setGiveStatus(GiveStatusEnum.GIVE_OVER);
        userCollection.setGiveSuccessTime(DateTime.now());
        userCollectionDao.updateStatusAndTimeById(userCollection.getId(), GiveStatusEnum.GIVE_OVER, DateTime.now());

        UserCollection toUser = addCollection(userCollection.getToUserId(), userCollection.getUserId(), userCollection.getCollectionId(), userCollection.getCollectionUuid(), userCollection.getCollectionImage(), userCollection.getLevel(), userCollection.getFirstTitle(),
                userCollection.getUserCreatorId(), ReceivedCollectionType.RECEIVED, userCollection.getBoxId(), userCollection.getBoxTitle(), userCollection.getBoxImage(), userCollection.getIsOpen(), userCollection.getProductId(), userCollection.getOrderId(), userCollection.getSecondOrderId(), userCollection.getBuyPrice(), userCollection.getNumbering(), userCollection.getId(), userCollection.getChainUrl(), AddCollectionEnum.DEFAULT, null, null, userCollection.getIsDaoSource());
        //藏品流转表记录
        CollectionCirculatingRecord collectionCirculatingRecord = new CollectionCirculatingRecord();
        collectionCirculatingRecord.setUserId(toUser.getUserId());
        collectionCirculatingRecord.setCollectionId(userCollection.getCollectionId());
        collectionCirculatingRecord.setReceivedCollectionType(ReceivedCollectionType.RECEIVED);
        DigitalCollection digitalCollection = digitalCollectionDao.getEcologyCollectionById(userCollection.getCollectionId());
        if (ObjectUtil.isNotNull(digitalCollection)) {
            userConsensusService.adjustConsensusService(userCollection.getToUserId(), digitalCollection.getId(), BigDecimal.ONE, UserConsensusTypeEnums.RECEIVE, userCollection.getFirstTitle(), null);
        }
        if (ObjectUtil.isEmpty(userCollection.getBoxId())) {
            collectionCirculatingRecord.setTypeClassify(ClassifyType.COLLECTION);
        } else {
            collectionCirculatingRecord.setTypeClassify(ClassifyType.BLIND_BOX);
        }
        collectionCirculatingRecord.setToUserCollection(toUser.getId());
        collectionCirculatingRecord.setToUserId(toUser.getUserId());
        collectionCirculatingRecord.setFromUserId(userCollection.getUserId());
        collectionCirculatingRecord.setFromUserCollection(userCollection.getId());
        collectionCirculatingRecord.insert();

        CollectionCirculatingRecord fromCollectionCirculatingRecord = new CollectionCirculatingRecord();
        fromCollectionCirculatingRecord.setUserId(userCollection.getUserId());
        fromCollectionCirculatingRecord.setCollectionId(userCollection.getCollectionId());
        fromCollectionCirculatingRecord.setReceivedCollectionType(ReceivedCollectionType.GIVE);
//            collectionCirculatingRecord.setCommodityType(CommodityType.PRODUCT);
        if (ObjectUtil.isEmpty(userCollection.getBoxId())) {
            fromCollectionCirculatingRecord.setTypeClassify(ClassifyType.COLLECTION);
        } else {
            fromCollectionCirculatingRecord.setTypeClassify(ClassifyType.BLIND_BOX);
        }
        fromCollectionCirculatingRecord.setToUserCollection(toUser.getId());
        fromCollectionCirculatingRecord.setToUserId(toUser.getUserId());
        fromCollectionCirculatingRecord.setFromUserId(userCollection.getUserId());
        fromCollectionCirculatingRecord.setFromUserCollection(userCollection.getId());
        fromCollectionCirculatingRecord.insert();
    }

    @Override
    public DonationFaceVO donationFaceVerification(String url) throws IOException {
        DonationFaceVO donationFaceVO = new DonationFaceVO();
        String resultMessage = "";
        Boolean flag = Boolean.FALSE;
        StaticData imgHost = staticDataDao.getByType("imgHost");
        url = imgHost.getValue() + url;
        UserInfo user = UserPool.getUser();
        if (!user.getIsSm()) {
            throw new GlobalRunTimeException(ErrorCode.USER_NOT_SM);
        }
        IdcardInfo idcardInfo = idcardInfoDao.getByUserIdAndIsPass(user.getId());
        if (ObjectUtil.isEmpty(idcardInfo)) {
            throw new GlobalRunTimeException(ErrorCode.USER_NOT_SM);
        }
        if (user.getIsTransferCheckFace()) {
            flag = true;
        } else {
            String s = IdCardAuditUtil.verifySelfieIdnumber(idcardInfo.getCardId(), idcardInfo.getName(), url);
            JSONObject jsonObject = JSONObject.parseObject(s);
            if ("OK".equals(jsonObject.getString("status"))) {
                String resultCode = jsonObject.getString("result_code");
                if ("1001".equals(resultCode)) {
                    flag = true;
                    user.setIsTransferCheckFace(Boolean.TRUE);
                    userInfoDao.updateIsTransferCheckFace(user.getId(), user.getIsTransferCheckFace());
                } else {
                    resultMessage = jsonObject.getString("result_message");
                    throw new GlobalRunTimeException(resultMessage);
                }
            } else {
                throw new GlobalRunTimeException(ErrorCode.AUDIT_FAILURE);
            }
        }

        donationFaceVO.setFlag(flag);
        donationFaceVO.setMsg(resultMessage);
        return donationFaceVO;
    }

    @Override
    public Page<TransferVO> transferLog(String fromUserAddress, String toUserAddress, String
            transactionHash, String chainUrl, int pageNo, int pageSize) {
        return userCollectionDao.transferLog(fromUserAddress, toUserAddress, transactionHash, chainUrl, pageNo, pageSize);
    }

    @Override
    public Page<UserCollectionVO> userCollection(String firstTitle, int pageNo, int pageSize, Date startTime, Date
            endTime, String userTel) {
        return userCollectionDao.userCollection(firstTitle, pageNo, pageSize, startTime, endTime, userTel);
    }

    @Override
    public List<UserCollectionExcelVO> userCollectionExcel(String firstTitle, Date startTime, Date endTime, String
            userTel) {
        return userCollectionDao.userCollectionExcel(firstTitle, startTime, endTime, userTel);
    }

    @Override
    public HavingPrivilegeCollectionDetailVO getPrivilegeCollectionDetail(Long id) {
        HavingPrivilegeCollectionDetailVO havingPrivilegeCollectionDetailVO = new HavingPrivilegeCollectionDetailVO();
        UserCollection userCollection = userCollectionDao.getUserCollectionById(id);
        if (ObjectUtil.isEmpty(userCollection)) {
            throw new GlobalRunTimeException(ErrorCode.NO_PRIVILEGED_COLLECTION);
        }
        DigitalCollection digitalCollection = digitalCollectionDao.getById(userCollection.getCollectionId());
        if (!digitalCollection.getIsPrivilege()) {
            throw new GlobalRunTimeException(ErrorCode.COLLECTION_IS_NOT_PRIVILEGED_COLLECTION);
        }
        havingPrivilegeCollectionDetailVO.setModelImg(digitalCollection.getModelImg());
        havingPrivilegeCollectionDetailVO.setModelDistance(digitalCollection.getModelDistance());
        Privilege privilege = privilegeDao.getByCollectionId(digitalCollection.getId());
        String equityListStr = "";
        StringBuilder stringBuilder = new StringBuilder();
        if (ObjectUtil.isNotEmpty(privilege)) {
            if (privilege.getIsAirdrop()) {
                stringBuilder.append("活动空投");
            }
            if (privilege.getFirstPayTime() > 0) {
                stringBuilder.append("\n优先购特权 (每月" + privilege.getFirstPayTime()).append("次)");
            }
            if (privilege.getTransferDiscount().compareTo(BigDecimal.ZERO) == 1) {
                String s = privilege.getTransferDiscount().movePointRight(1).stripTrailingZeros().toPlainString();
                stringBuilder.append("\n手续费折扣 (" + s).append("折)");
            }
            if (privilege.getIsIpShare()) {
                stringBuilder.append("\n热门ip分成");
            }
            equityListStr = stringBuilder.toString();
        }
        havingPrivilegeCollectionDetailVO.setCreationContent(digitalCollection.getCreationContent());
        havingPrivilegeCollectionDetailVO.setEquityListStr(equityListStr);
        havingPrivilegeCollectionDetailVO.setPrivilegeName(digitalCollection.getFirstTitle());
        havingPrivilegeCollectionDetailVO.setLevelName(PrivilegeCollectionLevelEnum.getValue(digitalCollection.getPrivilegeLevel()));
        havingPrivilegeCollectionDetailVO.setSkipUrl(digitalCollection.getSkipUrl());
        return havingPrivilegeCollectionDetailVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void mint(UserCollection userCollection) {
        UserChainAddr userChainAddr = userChainAddrDao.getByUserId(userCollection.getUserId());
        if (ObjectUtil.isNull(userChainAddr)) {
            log.error("用户{}未生成钱包地址", userCollection.getUserId());
            return;
        }
        Result<String> result = chainFeignClient.mint(new MintDTO(userChainAddr.getTokenAddress(), new BigInteger(userCollection.getCollectionUuid())));
        if (result.getCode() != 0) {
            log.error("藏品{}上链失败", userCollection.getId());
            userCollectionDao.updateChainUrl(userCollection.getId(), null, ChainStatusEnum.FAIL);
            return;
        }
        userCollectionDao.updateChainUrl(userCollection.getId(), result.getData(), ChainStatusEnum.ONLINE);

        ChainLog chainLog = new ChainLog();
        chainLog.setStatus(ChainStatusEnum.ONLINE);
        chainLog.setFormAddr(userChainAddr.getTokenAddress());
        chainLog.setCollectionUuid(userCollection.getCollectionUuid());
        chainLog.setTxId(result.getData());
        chainLog.setType(1);
        chainLog.insert();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void burn(UserCollection userCollection) {

        Result<String> result = chainFeignClient.burn(new BurnDTO(new BigInteger(userCollection.getCollectionUuid())));
        if (result.getCode() != 0) {
            log.error("藏品{}销毁失败", userCollection.getId());
            return;

        }
        userCollectionDao.updateChainUrl(userCollection.getId(), userCollection.getChainUrl(), ChainStatusEnum.OFFLINE);

        ChainLog chainLog = new ChainLog();
        chainLog.setStatus(ChainStatusEnum.ONLINE);
        chainLog.setCollectionUuid(userCollection.getCollectionUuid());
        chainLog.setType(3);

        chainLog.setTxId(result.getData());
        chainLog.insert();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void transfer(UserCollection userCollection) {
        UserChainAddr userChainAddr = userChainAddrDao.getByUserId(userCollection.getUserId());
        if (ObjectUtil.isNull(userChainAddr)) {
            log.error("用户{}未生成钱包地址", userCollection.getUserId());
            return;
        }
        UserChainAddr formUserChainAddr = userChainAddrDao.getByUserId(userCollection.getGiveUserId());

        Result<String> result = chainFeignClient.transfer(new TransferDTO(formUserChainAddr.getTokenAddress(), userChainAddr.getTokenAddress(), new BigInteger(userCollection.getCollectionUuid())));
        if (result.getCode() != 0) {
            log.error("藏品{}转增失败", userCollection.getId());
            return;

        }
        userCollectionDao.updateChainUrl(userCollection.getId(), result.getData(), ChainStatusEnum.OFFLINE);
        ChainLog chainLog = new ChainLog();
        chainLog.setStatus(ChainStatusEnum.ONLINE);
        chainLog.setFormAddr(userChainAddr.getTokenAddress());
        chainLog.setTxId(result.getData());
        chainLog.setType(2);
        chainLog.setCollectionUuid(userCollection.getCollectionUuid());

        chainLog.insert();
    }

    @Override
    public List<UserCollection> getListByCollercitonId(Long userId, Long collectionId) {
        return userCollectionDao.getListByCollercitonId(userId, collectionId);
    }

    @Override
    public List<UserCollection> getListByIds(List<Long> ids) {
        return userCollectionDao.getListByIds(ids);
    }

    @Override
    public Page<MyCollectionListByCollectionIdVO> myCollectionListByCollectionId(Long collectionId, Long
            userId, Integer pageNo, Integer pageSize) {

        return userCollectionDao.myCollectionListByCollectionId(collectionId, userId, pageNo, pageSize);
    }

    @Override
    public Page<MyCollectionListByCollectionIdVO> maintainCollectionListByCollectionId(Long collectionId, Long
            userId,
                                                                                       Integer pageNo, Integer pageSize,
                                                                                       BigDecimal lowPrice,
                                                                                       BigDecimal highPrice, CollectionOnConsignEnum onConsign) {
        return userCollectionDao.maintainCollectionListByCollectionId(collectionId, userId, pageNo, pageSize, lowPrice, highPrice, onConsign);
    }

    @Override
    public HavingCollectionDetailVO getCollectionDetail(UserInfo userInfo, Long id) {
        HavingCollectionDetailVO collectionDetail = new HavingCollectionDetailVO();
        UserCollection userCollection = userCollectionDao.getById(id);
        collectionDetail.setId(userCollection.getId());
        if (userCollection.getUserId().longValue() != UserPool.getUser().getId().longValue()) {
            throw new GlobalRunTimeException(ErrorCode.NO_ROLE);
        }
        collectionDetail.setFreezingStatus(userCollection.getFreezingStatus());
        //藏品
        DigitalCollection digitalCollection = digitalCollectionDao.getById(userCollection.getCollectionId());
        collectionDetail.setFirstTitle(digitalCollection.getFirstTitle());
        collectionDetail.setProductDetailPicture(digitalCollection.getProductDetailPicture());
        collectionDetail.setProductDetailPictureType(digitalCollection.getProductDetailPictureType());
        collectionDetail.setProductPresentation(digitalCollection.getProductPresentation());
        collectionDetail.setCreationContent(digitalCollection.getCreationContent());
        collectionDetail.setModelImg(digitalCollection.getModelImg());
        collectionDetail.setModelDistance(digitalCollection.getModelDistance());
        String privilegePresentation = digitalCollection.getPrivilegePresentation();
        if (ObjectUtil.isEmpty(privilegePresentation)) {
            privilegePresentation = "";
        }
        collectionDetail.setPrivilegePresentation(privilegePresentation);
        collectionDetail.setProductCount(digitalCollection.getSumCount());
        //作者
        UserCreatorInfo userCreatorInfo = userCreatorInfoDao.getById(digitalCollection.getUserCreatorId());
        collectionDetail.setNickName(userCreatorInfo.getDaoName());
        collectionDetail.setCreatorAvatarImg(userCreatorInfo.getCreatorAvatarImg());
        //系列
        CatenaInfo catenaInfo = catenaInfoDao.getById(digitalCollection.getCatenaId());
        collectionDetail.setCatenaName(catenaInfo.getName());

        Integer circulationNum = userCollectionDao.getCirculationNumByCollectionId(digitalCollection.getId());

        Integer sumCount = digitalCollection.getSumCount();
        Integer sumCirculationNum = digitalCollection.getCirculationNum() + circulationNum;
        if (sumCount < sumCirculationNum) {
            sumCirculationNum = sumCount;
        }
        collectionDetail.setCirculationNum(sumCirculationNum);
        collectionDetail.setCirculationCount(digitalCollection.getCirculationCount());
        StaticData staticData = staticDataDao.getByType("purchase_notes");
        collectionDetail.setPurchaseNotes(staticData.getValue());
        collectionDetail.setThreeModelId(digitalCollection.getThreeModelId());
        collectionDetail.setTopUpStatus(digitalCollection.getTopUpStatus());
        collectionDetail.setChainStatus(0);
        collectionDetail.setTianheChain("");
        //获取链信息
        CollectionChainDetailDTO collectionChainDetail = getCollectionChainDetail(userCollection);
        collectionDetail.setTianheChain(collectionChainDetail.getTianheChain());
        collectionDetail.setChainUrl(collectionChainDetail.getChainUrl());
        //collectionDetail.setContractAddress(collectionChainDetail.getContractAddress());
        Long between = 0L;
        Date createTime = userCollection.getCreateTime();
        if (ObjectUtil.isEmpty(createTime)) {
            createTime = userCollection.getModifyTime();
        }

        BigDecimal salesPrice = BigDecimal.ZERO;

        //交易确认中 :  allowConsign = false  isCancel = false isGive = false
        //按钮状态 1.可寄售: allowConsign = true  isCancel =false  isGive = false
        //按钮状态 2.取消: allowConsign = false  isCancel =true  isGive = false
        //按钮状态 2.可转增: allowConsign = false  isCancel =false  isGive = true
        Boolean allowConsign = Boolean.FALSE;
        Boolean isCancel = Boolean.FALSE;
        Boolean isGive = Boolean.FALSE;
        Boolean isTrade = Boolean.FALSE;
        Boolean isSpecialGive = Boolean.FALSE;
        //查询当前藏品在二级的配置
        SecondCollectionConfig secondCollectionConfig = secondCollectionConfigDao.getByCollectionIdAndStatus(userCollection.getCollectionId());
        SecondCollection secondCollection = secondCollectionDao.getOnShelfUserCollectionId(userCollection.getId());
        collectionDetail.setMarketType(BeanUtil.isNotEmpty(secondCollectionConfig) ? secondCollectionConfig.getMarketType() : null);
        //如果当前藏品在二级上架 就是可取消状态
        if (userCollection.getStatus() != ChainStatusEnum.ONLINE) {
            isTrade = Boolean.TRUE;
        } else {
            if (ObjectUtil.isNotEmpty(secondCollection)) {
                //如果当前的藏品是自己的  就是可以取消
                isCancel = Boolean.TRUE;
                salesPrice = secondCollection.getSalesPrice();
            } else if (ObjectUtil.isNotEmpty(secondCollectionConfig) && ObjectUtil.isNull(secondCollection)) {//如果当前藏品配置了可以上架二级 并且二级没有上架
                allowConsign = Boolean.TRUE;
                if (userInfo.getGiftPermission()) {
                    if (digitalCollection.getIsGive()) {
                        isSpecialGive = Boolean.TRUE;
                        if (ObjectUtil.isNotEmpty(createTime)) {
                            DateTime dateTime = DateUtil.offsetDay(createTime, digitalCollection.getLockupDays());
                            if (DateTime.now().after(dateTime)) {
                                isSpecialGive = Boolean.TRUE;
                            } else {
                                isSpecialGive = Boolean.FALSE;
                                between = dateTime.between(DateTime.now(), DateUnit.MS);
                            }
                        }
                    }
                }
            } else {//如果二级市场配置没有当前藏品 并且 也没有上级二级 就是可以转增
                if (digitalCollection.getIsGive()) {
                    isGive = Boolean.TRUE;
                    if (ObjectUtil.isNotEmpty(createTime)) {
                        DateTime dateTime = DateUtil.offsetDay(createTime, digitalCollection.getLockupDays());
                        if (DateTime.now().after(dateTime)) {
                            isGive = Boolean.TRUE;
                        } else {
                            isGive = Boolean.FALSE;
                            between = dateTime.between(DateTime.now(), DateUnit.MS);
                        }
                        if (digitalCollection.getTopUpStatus()) {
                            // 如果是充值类的藏品,判定该用户是否是城市服务中心
                            if (BeanUtil.isNotEmpty(usercityServiceCenterDao.getByUserId(userInfo.getId()))) {
                                isGive = Boolean.TRUE;
                            } else {
                                isGive = Boolean.FALSE;
                            }
                        }
                    }
                }
            }
        }
        if (UserPool.getUser().getUserTel().equals("13849904109") || UserPool.getUser().getUserTel().equals("16725719559")) {
            allowConsign = Boolean.FALSE;
        }
        collectionDetail.setIsSpecialGive(isSpecialGive);
        collectionDetail.setIsTrade(isTrade);
        collectionDetail.setIsCancel(isCancel);
        collectionDetail.setIsGive(isGive);
        collectionDetail.setAllowConsign(allowConsign);
        //最新成交价
        BigDecimal newPrice = secondOrderDao.getLastPrice(userCollection.getCollectionId());
        newPrice = ObjectUtil.isNull(newPrice) ? BigDecimal.ZERO : newPrice;

        collectionDetail.setSalesPrice(salesPrice.stripTrailingZeros().toPlainString());
        //发行价
//        String buyPrice = userCollectionDao.getIssuePrice(userCollection.getCollectionId(), userCollection.getUserId()).setScale(2, BigDecimal.ROUND_DOWN).toPlainString();
        BigDecimal issuePrice = digitalCollection.getIssuePrice();
        issuePrice = ObjectUtil.isNull(issuePrice) ? BigDecimal.ZERO : issuePrice;
        String buyPrice = issuePrice.setScale(2, BigDecimal.ROUND_DOWN).toPlainString();
        collectionDetail.setBuyPrice(buyPrice);
        collectionDetail.setIssuePrice(buyPrice);
        collectionDetail.setNewPrice(digitalCollection.getNewDeal().toPlainString());
        collectionDetail.setCollectionId(digitalCollection.getId());
        collectionDetail.setCountdown(between);
        collectionDetail.setNumbering(userCollection.getNumbering() + "/" + digitalCollection.getSumCount());
        collectionDetail.setSkipUrl(digitalCollection.getSkipUrl());
        collectionDetail.setContractAddress(collectionChainDetail.getContractAddress());
        collectionDetail.setLockedPositionTime(userCollection.getLockedPositionTime());
        collectionDetail.setIsSmeltingOnly(userCollection.getIsSmeltingOnly());
        PackageRule rule = packageRuleDao.getOpenByCollectionId(userCollection.getCollectionId());
        collectionDetail.setCanWriteOff(ObjectUtil.isNotNull(rule));

        collectionDetail.setConsensusNum("0.0");
        collectionDetail.setIsConsensusCollection(false);
        if (digitalCollection.getCollectionType() == DigitalMarketTypeEnum.ECOLOGY) {
            ExitConsensusUser exitConsensusUser = exitConsensusUserDao.getByUserId(UserPool.getUser().getId());
            if (ObjectUtil.isNotNull(exitConsensusUser) && exitConsensusUser.getStatus()) {
                collectionDetail.setConsensusNum(BigDecimal.ZERO.toPlainString());
                collectionDetail.setIsConsensusCollection(false);
            } else {
                UserCollectionConsensus userCollectionConsensus = userCollectionConsensusDao.getBuyUserIdAndCollectionId(UserPool.getUser().getId(), digitalCollection.getId());

                collectionDetail.setConsensusNum(ObjectUtil.isNull(userCollectionConsensus) ? "0.0" : userCollectionConsensus.getConsensusNum().toPlainString());
                collectionDetail.setIsConsensusCollection(true);
            }
        }
        return collectionDetail;
    }

    @Override
    public CollectionChainDetailDTO getCollectionChainDetail(UserCollection userCollection) {
        CollectionChainDetailDTO collectionChainDetailDTO = new CollectionChainDetailDTO();
        collectionChainDetailDTO.setTianheChain("");
        //链地址
        ChainStatusEnum status = userCollection.getStatus();
        if (status == ChainStatusEnum.ONLINE) {
            //String chainUrl = userCollection.getChainUrl();
            UserCollectionChainLog userCollectionChainLog = userCollectionChainLogDao.findTransactionHashByToUserCollectionId(userCollection.getId());
            String chainUrl = userCollectionChainLog.getTransactionHash();
            chainUrl = StrUtil.isBlank(chainUrl) ? ChainStatusEnum.NONE.getDescription() : chainUrl;
            collectionChainDetailDTO.setChainUrl(chainUrl);
            //如果
            if (!chainUrl.equals(ChainStatusEnum.ONLINE.getDescription())) {
                //天河链浏览器
                String tianheChain = staticDataDao.getByType("tianhe_chain").getValue();
                collectionChainDetailDTO.setTianheChain(tianheChain + chainUrl);
                collectionChainDetailDTO.setContractAddress(userCollectionChainLog.getContractAddress());
            }
        } else {
            collectionChainDetailDTO.setChainUrl(status.getDescription());
        }
        return collectionChainDetailDTO;
    }

    @Override
    public Page<CollectionChainRecord> getCollectionChainRecord(Long userId, String type, int pageNo, int pageSize) {
        Page<CollectionChainRecord> collectionChainRecord;
        if (type.equals("from")) {
            collectionChainRecord = userChainAddrDao.getCollectionChainRecord(userId, pageNo, pageSize);
        } else {
            collectionChainRecord = userChainAddrDao.getToUserIdCollectionChainRecord(userId, pageNo, pageSize);
        }

        List<CollectionChainRecord> records = collectionChainRecord.getRecords();
        if (records.size() > 0) {
            String tianheChain = staticDataDao.getByType("tianhe_chain").getValue();
            for (CollectionChainRecord record : records) {
                record.setTypeName(record.getType().getDescription());
                String transactionHash = record.getTransactionHash();
                if (StrUtil.isNotBlank(transactionHash)) {
                    record.setChainUrl(tianheChain + transactionHash);
                }
            }
        }
        return collectionChainRecord;
    }

    @Override
    public Page<TransferVO> getAdminCollectionChainRecord(String firstTitle, String fromUserAddress, String
            toUserAddress, String transactionHash, Integer collectionType, Integer status, Date startTime, Date
                                                                  endTime, Integer pageNo, Integer pageSize) {
        return userCollectionChainLogDao.getAdminCollectionChainRecord(firstTitle, fromUserAddress, toUserAddress, transactionHash, collectionType, status, startTime, endTime, pageNo, pageSize);
    }

    @Override
    public List<HoldCollectionVO> holdCollection(String collection) {
        // 请求回来的基础数据
        List<HoldCollectionDataVO> holdCollectionData = userCollectionChainLogDao.getHoldCollectionData(UserPool.getUser().getId(), collection);
        // 返回的集合
        List<HoldCollectionVO> holdCollections = new ArrayList<>();
        // 根据藏品id进行分组
        Map<Integer, List<HoldCollectionDataVO>> collect = holdCollectionData.stream().collect(Collectors.groupingBy(HoldCollectionDataVO::getCollectionId));
        // 循环处理map中的分组,把数据给循环组装起来
        collect.forEach((key, values) -> {
            // 持仓数量
            Integer positionNum = values.size();
            // 成本,该藏品 平均买入价  买入价总和/藏品数量,保存2位小数
            BigDecimal cost = values.stream().map(HoldCollectionDataVO::getProductPrice).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_DOWN);
            // 市价 该藏品 最新成交价
            BigDecimal marketPrice = values.get(0).getNewDeal();
            // 市值 该藏品 最新成交价*持仓数量
            BigDecimal marketValue = marketPrice.multiply(Convert.toBigDecimal(positionNum));
            // 盈亏 当前市值-总买入金额
            BigDecimal profitLoss = marketValue.subtract(cost);
            //盈亏率 盈亏/总买入金额 %
            BigDecimal profitLossRate = BigDecimal.ZERO;
            if (cost.compareTo(Convert.toBigDecimal(0)) == 0 || cost.compareTo(Convert.toBigDecimal(0)) == -1) {
                profitLossRate = new BigDecimal("0.00");
            } else {
                profitLossRate = profitLoss.divide(cost, 4, BigDecimal.ROUND_HALF_UP).multiply(Convert.toBigDecimal(100)).setScale(2, BigDecimal.ROUND_DOWN);
            }

            HoldCollectionVO holdCollection = new HoldCollectionVO();
            // 藏品名字
            holdCollection.setCollectionName(values.get(0).getFirstTitle());
            // 缩略图
            holdCollection.setCreationContent(values.get(0).getCreationContent());
            holdCollection.setCollectionId(values.get(0).getCollectionId());
            // 藏品数量
            holdCollection.setPositionNum(positionNum);
            // 成本价
            holdCollection.setCost(cost.divide(Convert.toBigDecimal(values.size()), 2, BigDecimal.ROUND_HALF_UP));
            // 市价
            holdCollection.setMarketPrice(marketPrice);
            // 市值
            holdCollection.setMarketValue(marketValue);
            // 盈亏
            holdCollection.setProfitLoss(profitLoss);
            // 盈亏率
            holdCollection.setProfitLossRate(profitLossRate);
            holdCollections.add(holdCollection);
        });
        return holdCollections;
    }

    @Override
    public SingleHoldCollection singleHoldCollection(Long id) {
        // 获取指定用户指定藏品id的藏品列表
        List<HoldCollectionDataVO> holdCollectionData = userCollectionChainLogDao.getSingleHoldCollectionDataByUserIdAndCollectionId(UserPool.getUser().getId(), id);
        SingleHoldCollection singleHoldCollection = new SingleHoldCollection();
        if (CollUtil.isEmpty(holdCollectionData)) {
            return singleHoldCollection;
        }

        // 持仓市值
        BigDecimal marketValue = holdCollectionData.get(0).getNewDeal().multiply(Convert.toBigDecimal(holdCollectionData.size()));
        // 市值
        singleHoldCollection.setMarketValue(marketValue);
        // 藏品名字
        singleHoldCollection.setCollectionName(holdCollectionData.get(0).getFirstTitle());
        // 最新成交价
        singleHoldCollection.setNewDeal(holdCollectionData.get(0).getNewDeal());
        // 获取昨天该商品最后一笔的成交价.如果是空的话,最新成交价就是0. 计算公式:(最新成交价-昨日最后成交价)/昨日最后成交价
        SecondOrder secondOrder = secondOrderDao.selectByRelationIdSubOneDayData(id);
        log.debug("昨日最后成交价为：", secondOrder);
        // 昨日最后成交价
        BigDecimal finishingStroke = BigDecimal.ZERO;
        if (!BeanUtil.isEmpty(secondOrder)) {
            finishingStroke = secondOrder.getBuyPrice();
        }
        // 缩略图
        singleHoldCollection.setCreationContent(holdCollectionData.get(0).getCreationContent());
        // 计算今日涨幅
        if (finishingStroke.compareTo(BigDecimal.ZERO) == 0 || finishingStroke.compareTo(BigDecimal.ZERO) == -1) {
            singleHoldCollection.setToDaysGains(new BigDecimal("0.00"));
        } else {
            BigDecimal toDaysGains = (holdCollectionData.get(0).getNewDeal().subtract(finishingStroke)).divide(finishingStroke, 4, BigDecimal.ROUND_HALF_UP).multiply(Convert.toBigDecimal(100)).setScale(2, BigDecimal.ROUND_DOWN);
            singleHoldCollection.setToDaysGains(toDaysGains);
        }
        return singleHoldCollection;
    }

    @Override
    public Page<SingleHoldCollectionDetails> singleHoldCollectionDetailsPage(Integer pageNo, Integer pageSize, Long
            id) {
        // 获取指定用户指定藏品id的藏品列表
        Page<HoldCollectionDataVO> holdCollectionData = userCollectionChainLogDao.getSingleHoldCollectionData(UserPool.getUser().getId(), pageNo, pageSize, id);
        List<HoldCollectionDataVO> holdCollectionDataRecords = holdCollectionData.getRecords();
        List<SingleHoldCollectionDetails> singleHoldCollectionDetails = new ArrayList<>();
        Page<SingleHoldCollectionDetails> singleHoldCollectionVOPage = new Page<>();
        if (CollUtil.isEmpty(holdCollectionDataRecords)) {
            return singleHoldCollectionVOPage;
        }

        for (HoldCollectionDataVO holdCollectionDatum : holdCollectionDataRecords) {
            SingleHoldCollectionDetails singleHoldCollectionDetail = new SingleHoldCollectionDetails();
            singleHoldCollectionDetail.setCollectionId(StrUtil.format("{}/{}", holdCollectionDatum.getNumbering(), holdCollectionDatum.getSumCount()));
            singleHoldCollectionDetail.setCost(holdCollectionDatum.getProductPrice().setScale(2, BigDecimal.ROUND_DOWN));
            singleHoldCollectionDetail.setProfitLoss(holdCollectionDatum.getNewDeal().subtract(holdCollectionDatum.getProductPrice()));
            if (holdCollectionDatum.getProductPrice().compareTo(BigDecimal.ZERO) == 0 || holdCollectionDatum.getProductPrice().compareTo(BigDecimal.ZERO) == -1) {
                singleHoldCollectionDetail.setProfitLossRate(new BigDecimal("0.00"));
            } else {
                singleHoldCollectionDetail.setProfitLossRate((holdCollectionDatum.getNewDeal().subtract(holdCollectionDatum.getProductPrice())).divide(holdCollectionDatum.getProductPrice(), 4, BigDecimal.ROUND_DOWN).multiply(Convert.toBigDecimal(100)).setScale(2, BigDecimal.ROUND_DOWN));
            }
            singleHoldCollectionDetails.add(singleHoldCollectionDetail);
        }

        singleHoldCollectionVOPage.setRecords(singleHoldCollectionDetails);
        singleHoldCollectionVOPage.setTotal(holdCollectionData.getTotal());
        singleHoldCollectionVOPage.setSize(holdCollectionData.getSize());
        singleHoldCollectionVOPage.setCurrent(holdCollectionData.getCurrent());
        return singleHoldCollectionVOPage;
    }


    @Override
    public Boolean getUserApplyCreatedDaoCastellanRights() {
        // 获取用户城主卡,获取的时候考虑用户有多张城主卡的情况,只获取ID最小的那一条.
        StaticData cityLordCollectionId = staticDataDao.getByType("city_lord_collection_id");
        // 城主卡的藏品id
        Long value = Convert.toLong(cityLordCollectionId.getValue());
        // 根据城主卡藏品id,获取用户藏品的对应数据.如果为空的话,则报错.如果不为空的话,获取的id最小的一条进行绑定到这个dao上.
        UserCollection userApplyCreatedDaoCastellanRights = userCollectionDao.getUserApplyCreatedDaoCastellanRights(value);
        if (BeanUtil.isEmpty(userApplyCreatedDaoCastellanRights)) {
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }

    @Override
    public int getIsContainsAndIsHoldAndIsOpenAndOnConsignByCollectionId(Long collectionId, Long userId) {
        return userCollectionDao.getIsContainsAndIsHoldAndIsOpenAndOnConsignByCollectionId(collectionId, userId);
    }

    @Override
    public int getIsContainsAndIsHoldAndIsOpenAndOnConsignByCollectionIds(List<Long> collectionIds, Long userId) {
        return userCollectionDao.getIsContainsAndIsHoldAndIsOpenAndOnConsignByCollectionIds(collectionIds, userId);
    }

    @Override
    public List<UserCollection> getUserCollectionListByCollectionIdAndUserIdAndSize(Long collectionId, Long
            userId, Integer num) {
        return userCollectionDao.getUserCollectionListByCollectionIdAndUserIdAndSize(collectionId, userId, num);
    }

    @Override
    public Page<UserHoldCollectionVO> getPageByUserIdAndCollectionId(Long userId, Long collectionId, Integer
            pageNo, Integer pageSize) {
        return userCollectionDao.getPageByUserIdAndCollectionId(userId, collectionId, pageNo, pageSize);
    }

    @Override
    public List<UserCollection> getListByUserIdAndCollectionIdAndIds(Long userId, Long
            collectionId, List<Long> userCollectionIdList) {
        return userCollectionDao.getListByUserIdAndCollectionIdAndIds(userId, collectionId, userCollectionIdList);
    }

    @Override
    public List<UserCollection> getListByUserIdAndCollectionIdAndCount(Long userId, Long collectionId, Integer
            collectionPledgeCount) {
        return userCollectionDao.getListByUserIdAndCollectionIdAndCount(userId, collectionId, collectionPledgeCount);
    }


    @Override
    public List<UserCollection> getListByUserIdAndCollectionIdAndCount(Long userId, Long
            collectionId, List<Long> userCollectionIdList) {
        return userCollectionDao.getListByUserIdAndCollectionIdAndCount(userId, collectionId, userCollectionIdList);
    }

    @Override
    public List<UserCollection> pledgeSecretMaxCount(Long userId, Long collectionId) {
        return userCollectionDao.pledgeSecretMaxCount(userId, collectionId);
    }

    @Override
    public Integer getPledgeSecretByUserIdAndCollectionId(Long id, Long collectionId) {
        return userCollectionDao.getPledgeSecretByUserIdAndCollectionId(id, collectionId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void collectionGive(CollectionGiveDTO request) {
        // 最基本的要求 用户是有效用户
        if (!request.getUserInfo().getIsValid()) {
            throw new GlobalRunTimeException(ErrorCode.IF_YOU_HAVA_NOT_BECOME_A_VALID_USER_YOU_CANNOT_TRANSFER);
        }
        // 市值账号的判定,如果他是市值账号的话那么把他定义成有效用户
        FilterIncomeList isTeamIncomeByUserId = filterIncomeListDao.getIsTeamIncomeByUserId(request.getUserInfo().getId());
        if (!ObjectUtil.isNull(isTeamIncomeByUserId)) {
            request.getUserInfo().setIsValid(Boolean.TRUE);
        }
        // 验证要转增的藏品是否存在
        UserCollection userCollection = userCollectionDao.getById(request.getId());
        if (BeanUtil.isEmpty(userCollection)) {
            throw new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND);
        }
        UserChainInfo giftUserChainInfo = userChainInfoDao.getByUserId(request.getUserInfo().getId());
        request.setGiftUserChainInfo(giftUserChainInfo);
        if (!request.selfDenial()) {
            throw new GlobalRunTimeException("赠送人不能是自己");
        }
        switch (userCollection.getFreezingStatus()) {
            case NORMAL:
                break;
            case VERY_ACTIVE:
                throw new GlobalRunTimeException("该藏品正在激活秘境，无法转增");
            case PRESSING:
                throw new GlobalRunTimeException("该藏品正在秘境挖宝，无法转增");
            case LOCK:
                throw new GlobalRunTimeException("该藏品正在参加拍卖，无法转增");
            case OPEN_SHOP:
                throw new GlobalRunTimeException("该藏品正在开启店铺，无法转增");
        }

        // 判定转增的时候这个藏品是否存在,因为要知道这个藏品的状态是否是可以转赠的
        DigitalCollection digitalCollection = digitalCollectionDao.getById(userCollection.getCollectionId());
        if (BeanUtil.isEmpty(digitalCollection)) {
            throw new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND);
        }

        if (!digitalCollection.getIsGive()) {
            throw new GlobalRunTimeException("该藏品无法转增");
        }
        // 密码验证器,错误会直接抛出异常.
        request.passwordVerifier();
        // 根据地址,获取用户
        UserChainInfo registerByUserId = userChainInfoDao.getByAddr(request.getAddress());
        UserInfo complimentarySubscriber = userInfoDao.getById(registerByUserId.getUserId());
        request.setComplimentarySubscriber(complimentarySubscriber);
        // 藏品效验器
        verifyCollection(userCollection, request.getUserInfo());
        if (!userCollection.getIsOpen() && userCollection.getStatus() == ChainStatusEnum.NONE) {
            userCollection.setStatus(ChainStatusEnum.ONLINE);
        }
        if (userCollection.getStatus() != ChainStatusEnum.ONLINE) {
            throw new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_ONLINE);
        }
        // 需要确定他是不是盲盒,如果是盲盒的话要单独做判定
        if (!userCollection.getIsOpen() && userCollection.getBoxId() != null && userCollection.getBoxId() != 0L) {
            BoxProduct boxProduct = boxProductDao.getById(userCollection.getBoxId());
            if (ObjectUtil.isEmpty(boxProduct)) {
                throw new GlobalRunTimeException(ErrorCode.MALL_PRODUCT_DOES_NOT_EXIST);
            }
            if (!boxProduct.getIsGive()) {
                throw new GlobalRunTimeException(ErrorCode.THIS_COLLECTION_CANNOT_BE_TRANSFERRED);
            }
        }
        List<CollectionGift> collectionGifts = collectionGiftDao.getCollectionId(digitalCollection.getId());
        request.calculate(collectionGifts, 1);
        String remark = StrUtil.format("转赠藏品消耗");

        List<Integer> collect = collectionGifts.stream().map(CollectionGift::getConsumeType).collect(Collectors.toList());
        if (!collect.contains(request.getConsumeType())) {
            throw new GlobalRunTimeException("当前不支持该类型转增");
        }

        // 记录扣除所需要的钱或者星球碎片消耗 或者生态燃料
        // 记录用户转增数据日志
        CollectionGiftLog collectionGiftLog = new CollectionGiftLog();
        if (request.getConsumeType().equals(1)) {
            collectionGiftLog.setPaymentSum(request.getDebris());
            userAssetsService.subIntegralByUserId(request.getDebris(), request.getUserInfo().getId(), CoinCategoryEnum.INTEGRAL, AssetChangeLogEnum.GIFT, 0L, StrUtil.format("转赠{}藏品消耗", complimentarySubscriber.getNickName()));
        } else if (request.getConsumeType().equals(2)) {
            UserWallet byUserId = userWalletService.getByUserId(request.getUserInfo().getId());
            if (NumberUtil.isLess(byUserId.getBalance().add(byUserId.getPayBalance()), request.getAmount())) {
                throw new GlobalRunTimeException("余额不足");
            }
            request.setUserWallet(byUserId);
            BigDecimal payBalance = request.getUserWallet().getPayBalance();
            // 扣钱.
            //1.先扣支付余额 2.再扣提现余额
            if (payBalance.compareTo(request.getAmount()) >= 0) { //如果支付账户足够 直接从支付账户扣
                collectionGiftLog.setPaymentSum(request.getAmount());
                Assert.isTrue(userWalletService.subBalance(request.getUserWallet(), request.getAmount(), 0L, WalletDetailTypeEnum.NFT_TRANSFER_CREDIT, UserBalanceTypeEnum.PAY_BALANCE, remark), () -> new GlobalRunTimeException(ErrorCode.PAYMENT_FAILED));
            } else {//如果支付账户没钱
                if (payBalance.compareTo(BigDecimal.ZERO) == 0) {//支付账户没钱,直接扣提现账户
                    collectionGiftLog.setPaymentSum(request.getAmount());
                    Assert.isTrue(userWalletService.subBalance(request.getUserWallet(), request.getAmount(), 0L, WalletDetailTypeEnum.NFT_TRANSFER, UserBalanceTypeEnum.BALANCE, remark), () -> new GlobalRunTimeException(ErrorCode.PAYMENT_FAILED));
                } else {//如果支付账户有钱 但是不够
                    //先扣除支付账户
                    collectionGiftLog.setPaymentSum(request.getAmount());
                    Assert.isTrue(userWalletService.subBalance(request.getUserWallet(), payBalance, 0L, WalletDetailTypeEnum.NFT_TRANSFER_CREDIT, UserBalanceTypeEnum.PAY_BALANCE, remark), () -> new GlobalRunTimeException(ErrorCode.PAYMENT_FAILED));
                    BigDecimal subtract = request.getAmount().subtract(payBalance);
                    Assert.isTrue(userWalletService.subBalance(request.getUserWallet(), subtract, 0L, WalletDetailTypeEnum.NFT_TRANSFER, UserBalanceTypeEnum.BALANCE, remark), () -> new GlobalRunTimeException(ErrorCode.PAYMENT_FAILED));
                }
            }
        } else {
            //生态燃料扣除
            UserEcologyPoints userEcologyPoints = userEcologyPointsService.getOneByUserId(request.getUserInfo().getId());
            if (NumberUtil.isGreater(request.getEcology(), userEcologyPoints.getAmount())) {
                throw new GlobalRunTimeException("生态燃料不足");
            }
            collectionGiftLog.setPaymentSum(request.getEcology());
            Assert.isTrue(userEcologyPointsService.subAmount(request.getUserInfo().getId(), request.getEcology(), EcologyPointsEnum.GIFT_PROPS, StrUtil.format("转赠{}藏品消耗", complimentarySubscriber.getNickName(), digitalCollection.getFirstTitle())), () -> new GlobalRunTimeException("扣除生态燃料失败"));
        }

        UserInfo toUser = userInfoDao.getByUUID(complimentarySubscriber.getUserUuid());
        Assert.notNull(toUser, () -> new GlobalRunTimeException(ErrorCode.THE_USER_DOES_NOT_EXIST));
        Assert.isFalse(toUser.getIsFreeze(), () -> new GlobalRunTimeException(ErrorCode.THE_USER_DOES_NOT_EXIST));
        Assert.isTrue(toUser.getIsSm(), () -> new GlobalRunTimeException(ErrorCode.USER_NOT_SM));

        userCollection.setGiveStatus(GiveStatusEnum.GIVING);
        userCollection.setGiveTime(DateTime.now());
        userCollection.setIsHold(false);
        userCollection.setToUserId(toUser.getId());
        if (!userCollection.updateById()) {
            throw new GlobalRunTimeException(ErrorCode.THE_SYSTEM_IS_BUSY_PLEASE_TRY_AGAIN_LATER);
        }

        privilegeService.flushUserLevel(userCollection.getUserId());

        //降级逻辑
        daoService.downgrade(userCollection.getCollectionId(), userCollection.getUserId(), ReceivedCollectionType.GIVE);
        collectionGiftLog.setCollectionId(digitalCollection.getId());
        collectionGiftLog.setTitle(digitalCollection.getFirstTitle());
        collectionGiftLog.setNumbering(userCollection.getNumbering());
        collectionGiftLog.setNumberingList(userCollection.getNumbering().toString());
        collectionGiftLog.setConsumeType(request.getConsumeType());
        collectionGiftLog.setQuantityConsume("1");
        collectionGiftLog.setAddress(request.getAddress());
        collectionGiftLog.setGiftUserId(request.getUserInfo().getId());
        collectionGiftLog.setReceiveUserId(request.getComplimentarySubscriber().getId());
        collectionGiftLog.setGiftPropIds(Convert.toStr(request.getId()));
        collectionGiftLog.insert();
        if (digitalCollection.getCollectionType() == DigitalMarketTypeEnum.ECOLOGY) {
            userConsensusService.adjustConsensusService(request.getUserInfo().getId(), digitalCollection.getId(), BigDecimal.ONE.negate(), UserConsensusTypeEnums.GIVE, digitalCollection.getFirstTitle(), null);
        }

        //转赠上链费
        if (digitalCollection.getIsGive() && digitalCollection.getGasCost().compareTo(BigDecimal.ZERO)>=1){
            GasConsumeDTO gasConsume = getGasConsumeDTO(request, digitalCollection);
            orderGasService.gasConsume(gasConsume);
        }

    }

    private static GasConsumeDTO getGasConsumeDTO(CollectionGiveDTO request, DigitalCollection digitalCollection) {
        GasConsumeDTO gasConsume=new GasConsumeDTO();
        gasConsume.setConsumeCost(digitalCollection.getGasCost());
        gasConsume.setUserId(request.getUserInfo().getId());
        gasConsume.setGasConsumeType(GasConsumeTypeEnum.BALANCE);
        gasConsume.setWalletDetailType(WalletDetailTypeEnum.GAS_GIVE);
        gasConsume.setProductId(0L);
        gasConsume.setCollectionId(digitalCollection.getId());
        gasConsume.setOrderGasType(OrderGasTypeEnum.GAS_GIVE);
        return gasConsume;
    }


    /**
     * 藏品批量转增
     *
     * @param request
     */
    @Override
    public void collectionBatchGive(CollectionBatchGiveDTO request) {
        //转增数量
        request.setCollectionIdList(request.getCollectionIdList().stream().distinct().collect(Collectors.toList()));
        // 最基本的要求 用户是有效用户
        if (!request.getUserInfo().getIsValid()) {
            throw new GlobalRunTimeException(ErrorCode.IF_YOU_HAVA_NOT_BECOME_A_VALID_USER_YOU_CANNOT_TRANSFER);
        }
        // 市值账号的判定,如果他是市值账号的话那么把他定义成有效用户
        FilterIncomeList isTeamIncomeByUserId = filterIncomeListDao.getIsTeamIncomeByUserId(request.getUserInfo().getId());
        if (!ObjectUtil.isNull(isTeamIncomeByUserId)) {
            request.getUserInfo().setIsValid(Boolean.TRUE);
        }
        // 验证要转增的藏品是否存在
//        UserCollection userCollection = userCollectionDao.getById(request.getId());
        List<UserCollection> userCollectionList = userCollectionDao.listByIdListAndUserId(request.getUserInfo().getId(), request.getCollectionIdList());
        if (CollectionUtils.isEmpty(userCollectionList) || userCollectionList.size() != request.getCollectionIdList().size()) {
            throw new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND);
        }
        List<Long> collectionIdList = userCollectionList.stream().map(UserCollection::getCollectionId).distinct().collect(Collectors.toList());
        if (collectionIdList.size() > 1) {
            throw new GlobalRunTimeException(ErrorCode.NOT_SAME_COLLECTION);
        }
        Long collectionId = collectionIdList.get(0);
        UserChainInfo giftUserChainInfo = userChainInfoDao.getByUserId(request.getUserInfo().getId());
        request.setGiftUserChainInfo(giftUserChainInfo);
        if (!request.selfDenial()) {
            throw new GlobalRunTimeException("赠送人不能是自己");
        }

        // 判定转增的时候这个藏品是否存在,因为要知道这个藏品的状态是否是可以转赠的
        DigitalCollection digitalCollection = digitalCollectionDao.getById(collectionId);
        if (BeanUtil.isEmpty(digitalCollection)) {
            throw new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND);
        }

        if (!digitalCollection.getIsGive()) {
            throw new GlobalRunTimeException("该藏品无法转增");
        }
        // 密码验证器,错误会直接抛出异常.
        request.passwordVerifier();
        // 根据地址,获取用户
        UserChainInfo registerByUserId = userChainInfoDao.getByAddr(request.getAddress());
        if (ObjectUtil.isNull(registerByUserId)) {
            throw new GlobalRunTimeException("接收用户无效");
        }
        UserInfo complimentarySubscriber = userInfoDao.getById(registerByUserId.getUserId());
        if (ObjectUtil.isNull(complimentarySubscriber) || !complimentarySubscriber.getIsSm()) {
            throw new GlobalRunTimeException("接收用户无效");
        }
        request.setComplimentarySubscriber(complimentarySubscriber);
        // 藏品效验器
        userCollectionList.forEach(userCollection -> {
            verifyCollection(userCollection, request.getUserInfo());
            if (!userCollection.getIsOpen() && userCollection.getStatus() == ChainStatusEnum.NONE) {
                userCollection.setStatus(ChainStatusEnum.ONLINE);
            }
            if (userCollection.getStatus() != ChainStatusEnum.ONLINE) {
                throw new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_ONLINE);
            }
            if (userCollection.getOnConsign() != CollectionOnConsignEnum.NORMAL) {
                throw new GlobalRunTimeException(ErrorCode.COLLECTION_ON_SIGN);
            }
            // 需要确定他是不是盲盒,如果是盲盒的话要单独做判定
            if (!userCollection.getIsOpen() && userCollection.getBoxId() != null && userCollection.getBoxId() != 0L) {
                BoxProduct boxProduct = boxProductDao.getById(userCollection.getBoxId());
                if (ObjectUtil.isEmpty(boxProduct)) {
                    throw new GlobalRunTimeException(ErrorCode.MALL_PRODUCT_DOES_NOT_EXIST);
                }
                if (!boxProduct.getIsGive()) {
                    throw new GlobalRunTimeException(ErrorCode.THIS_COLLECTION_CANNOT_BE_TRANSFERRED);
                }
            }
        });
        List<CollectionGift> collectionGifts = collectionGiftDao.getCollectionId(digitalCollection.getId());
        request.calculate(collectionGifts, request.getCollectionIdList().size());
        String remark = StrUtil.format("转赠藏品消耗");
        List<Integer> collect = collectionGifts.stream().map(CollectionGift::getConsumeType).collect(Collectors.toList());
        if (!collect.contains(request.getConsumeType())) {
            throw new GlobalRunTimeException("当前不支持该类型转增");
        }
        // 记录扣除所需要的钱或者星球碎片消耗 或者生态燃料
        // 记录用户转增数据日志
        CollectionGiftLog collectionGiftLog = new CollectionGiftLog();
        if (request.getConsumeType().equals(1)) {
            collectionGiftLog.setPaymentSum(request.getDebris());
            userAssetsService.subIntegralByUserId(request.getDebris(), request.getUserInfo().getId(), CoinCategoryEnum.INTEGRAL, AssetChangeLogEnum.GIFT, 0L, StrUtil.format("转赠{}藏品消耗", complimentarySubscriber.getNickName()));
        } else if (request.getConsumeType().equals(2)) {
            UserWallet byUserId = userWalletService.getByUserId(request.getUserInfo().getId());
            if (NumberUtil.isLess(byUserId.getBalance().add(byUserId.getPayBalance()), request.getAmount())) {
                throw new GlobalRunTimeException("余额不足");
            }
            request.setUserWallet(byUserId);
            BigDecimal payBalance = request.getUserWallet().getPayBalance();
            // 扣钱.
            //1.先扣支付余额 2.再扣提现余额
            if (payBalance.compareTo(request.getAmount()) >= 0) { //如果支付账户足够 直接从支付账户扣
                collectionGiftLog.setPaymentSum(request.getAmount());
                Assert.isTrue(userWalletService.subBalance(request.getUserWallet(), request.getAmount(), 0L, WalletDetailTypeEnum.NFT_TRANSFER_CREDIT, UserBalanceTypeEnum.PAY_BALANCE, remark), () -> new GlobalRunTimeException(ErrorCode.PAYMENT_FAILED));
            } else {//如果支付账户没钱
                if (payBalance.compareTo(BigDecimal.ZERO) == 0) {//支付账户没钱,直接扣提现账户
                    collectionGiftLog.setPaymentSum(request.getAmount());
                    Assert.isTrue(userWalletService.subBalance(request.getUserWallet(), request.getAmount(), 0L, WalletDetailTypeEnum.NFT_TRANSFER, UserBalanceTypeEnum.BALANCE, remark), () -> new GlobalRunTimeException(ErrorCode.PAYMENT_FAILED));
                } else {//如果支付账户有钱 但是不够
                    //先扣除支付账户
                    collectionGiftLog.setPaymentSum(request.getAmount());
                    Assert.isTrue(userWalletService.subBalance(request.getUserWallet(), payBalance, 0L, WalletDetailTypeEnum.NFT_TRANSFER_CREDIT, UserBalanceTypeEnum.PAY_BALANCE, remark), () -> new GlobalRunTimeException(ErrorCode.PAYMENT_FAILED));
                    BigDecimal subtract = request.getAmount().subtract(payBalance);
                    Assert.isTrue(userWalletService.subBalance(request.getUserWallet(), subtract, 0L, WalletDetailTypeEnum.NFT_TRANSFER, UserBalanceTypeEnum.BALANCE, remark), () -> new GlobalRunTimeException(ErrorCode.PAYMENT_FAILED));
                }
            }
        } else {
            //生态燃料扣除
            UserEcologyPoints userEcologyPoints = userEcologyPointsService.getOneByUserId(request.getUserInfo().getId());
            if (NumberUtil.isGreater(request.getEcology(), userEcologyPoints.getAmount())) {
                throw new GlobalRunTimeException("生态燃料不足");
            }
            collectionGiftLog.setPaymentSum(request.getEcology());
            Assert.isTrue(userEcologyPointsService.subAmount(request.getUserInfo().getId(), request.getEcology(), EcologyPointsEnum.GIFT_PROPS, StrUtil.format("转赠{}藏品消耗", complimentarySubscriber.getNickName(), digitalCollection.getFirstTitle())), () -> new GlobalRunTimeException("扣除生态燃料失败"));
        }

        UserInfo toUser = userInfoDao.getByUUID(complimentarySubscriber.getUserUuid());
        Assert.notNull(toUser, () -> new GlobalRunTimeException(ErrorCode.THE_USER_DOES_NOT_EXIST));
        Assert.isFalse(toUser.getIsFreeze(), () -> new GlobalRunTimeException(ErrorCode.THE_USER_DOES_NOT_EXIST));
        Assert.isTrue(toUser.getIsSm(), () -> new GlobalRunTimeException(ErrorCode.USER_NOT_SM));
        userCollectionList.stream().forEach(userCollection -> {
            userCollection.setGiveStatus(GiveStatusEnum.GIVING);
            userCollection.setGiveTime(DateTime.now());
            userCollection.setIsHold(false);
            userCollection.setToUserId(toUser.getId());
            if (!userCollection.updateById()) {
                throw new GlobalRunTimeException(ErrorCode.THE_SYSTEM_IS_BUSY_PLEASE_TRY_AGAIN_LATER);
            }
        });
        privilegeService.flushUserLevel(request.getUserInfo().getId());

        //降级逻辑
        daoService.downgrade(collectionId, request.getUserInfo().getId(), ReceivedCollectionType.GIVE);
        collectionGiftLog.setCollectionId(digitalCollection.getId());
        collectionGiftLog.setTitle(digitalCollection.getFirstTitle());
        collectionGiftLog.setNumbering(0);
        collectionGiftLog.setNumberingList(userCollectionList.stream().map(UserCollection::getNumbering).map(String::valueOf).collect(Collectors.joining(",")));
        collectionGiftLog.setConsumeType(request.getConsumeType());
        collectionGiftLog.setQuantityConsume(String.valueOf(request.getCollectionIdList().size()));
        collectionGiftLog.setAddress(request.getAddress());
        collectionGiftLog.setGiftUserId(request.getUserInfo().getId());
        collectionGiftLog.setReceiveUserId(request.getComplimentarySubscriber().getId());
        collectionGiftLog.setGiftPropIds(request.getCollectionIdList().stream().map(String::valueOf).collect(Collectors.joining(",")));
        collectionGiftLog.insert();

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void collectionGiveDao(CollectionGiveDaoRequest collectionGiveDTO) {
        UserInfo user = userInfoDao.getOneByUserTel(collectionGiveDTO.getGiftUserTel());

        collectionGiveDTO.setUserInfo(user);
        // 最基本的要求 用户是有效用户
        if (!collectionGiveDTO.getUserInfo().getIsValid()) {
            throw new GlobalRunTimeException("还未成为有效用户,不能转账哦");
        }
        // 市值账号的判定,如果他是市值账号的话那么把他定义成有效用户
        FilterIncomeList isTeamIncomeByUserId = filterIncomeListDao.getIsTeamIncomeByUserIdAndDaoId(collectionGiveDTO.getDaoId(), collectionGiveDTO.getUserInfo().getId());
        if (!ObjectUtil.isNull(isTeamIncomeByUserId)) {
            collectionGiveDTO.getUserInfo().setIsValid(Boolean.TRUE);
        }
        // 验证要转增的藏品是否存在
        UserCollection userCollection = userCollectionDao.getById(collectionGiveDTO.getId());
        if (BeanUtil.isEmpty(userCollection)) {
            throw new GlobalRunTimeException("未找到藏品");
        }
        UserChainInfo giftUserChainInfo = userChainInfoDao.getByUserId(collectionGiveDTO.getUserInfo().getId());
        collectionGiveDTO.setGiftUserChainInfo(giftUserChainInfo);

        switch (userCollection.getFreezingStatus()) {
            case NORMAL:
                break;
            case VERY_ACTIVE:
                throw new GlobalRunTimeException("该藏品正在激活秘境，无法转增");
            case PRESSING:
                throw new GlobalRunTimeException("该藏品正在秘境挖宝，无法转增");
            case LOCK:
                throw new GlobalRunTimeException("该藏品正在参加拍卖，无法转增");
            case OPEN_SHOP:
                throw new GlobalRunTimeException("该藏品正在开启店铺，无法转增");
        }
        // 判定转增的时候这个藏品是否存在,因为要知道这个藏品的状态是否是可以转赠的
        DigitalCollection digitalCollection = digitalCollectionDao.getById(userCollection.getCollectionId());
        if (BeanUtil.isEmpty(digitalCollection)) {
            throw new GlobalRunTimeException("未找到藏品");
        }
        /*if (!digitalCollection.getIsGive()) {
            throw new GlobalRunTimeException("该藏品无法转增");
        }*/
        //根据接收方手机号 获取用户 以及地址
        UserInfo complimentarySubscriber = userInfoDao.getOneByUserTel(collectionGiveDTO.getReceiveUserTel());
        if (Objects.isNull(complimentarySubscriber)) {
            throw new GlobalRunTimeException("未找到此手机号用户");
        }
        List<Long> userBelongingToDao = userCreatorInfoDao.getUserBelongingToDao(complimentarySubscriber.getId());
        if (CollectionUtils.isEmpty(userBelongingToDao) || !userBelongingToDao.contains(collectionGiveDTO.getDaoId())) {
            throw new GlobalRunTimeException("接收方非本网体下用户");
        }
        UserChainInfo receiveGiftUserChainInfo = userChainInfoDao.getByUserId(complimentarySubscriber.getId());
        collectionGiveDTO.setComplimentarySubscriber(complimentarySubscriber);
        collectionGiveDTO.setAddress(receiveGiftUserChainInfo.getAddress());
        if (!collectionGiveDTO.selfDenial()) {
            throw new GlobalRunTimeException("赠送人不能是自己");
        }
        // 藏品效验器
        verifyCollection(userCollection, collectionGiveDTO.getUserInfo());
        if (!userCollection.getIsOpen() && userCollection.getStatus() == ChainStatusEnum.NONE) {
            userCollection.setStatus(ChainStatusEnum.ONLINE);
        }
        if (userCollection.getStatus() != ChainStatusEnum.ONLINE) {
            throw new GlobalRunTimeException("藏品铸造未完成");
        }
        // 需要确定他是不是盲盒,如果是盲盒的话要单独做判定
        if (!userCollection.getIsOpen() && userCollection.getBoxId() != null && userCollection.getBoxId() != 0L) {
            BoxProduct boxProduct = boxProductDao.getById(userCollection.getBoxId());
            if (ObjectUtil.isEmpty(boxProduct)) {
                throw new GlobalRunTimeException("商品不存在");
            }
            if (!boxProduct.getIsGive()) {
                throw new GlobalRunTimeException("此藏品不能转赠");
            }
        }
        //List<CollectionGift> collectionGifts = collectionGiftDao.getCollectionId(digitalCollection.getId());
        //collectionGiveDTO.calculate_(collectionGiveDTO.getCount(), 1);
        String remark = StrUtil.format("转赠藏品消耗");
        if (collectionGiveDTO.getConsumeType() != 2) {
            throw new GlobalRunTimeException("当前不支持该类型转增");
        }

        // 记录扣除所需要的钱或者星球碎片消耗 或者生态燃料
        // 记录用户转增数据日志
        CollectionGiftLog collectionGiftLog = new CollectionGiftLog();
        DaoWallet daoWallet = daoWalletDao.getByDaoId(collectionGiveDTO.getDaoId());
        if (NumberUtil.isLess(daoWallet.getBalance(), BigDecimal.valueOf(1))) {
            throw new GlobalRunTimeException("余额不足");
        }
        collectionGiveDTO.setDaoWallet(daoWallet);
        daoWalletService.subBalance(collectionGiveDTO.getDaoId(), null, BigDecimal.valueOf(1), BigDecimal.ZERO, DaoWalletTypeEnum.COLLECTION_GIVE, remark);
        UserInfo toUser = userInfoDao.getByUUID(complimentarySubscriber.getUserUuid());
        Assert.notNull(toUser, () -> new GlobalRunTimeException("该用户不存在"));
        Assert.isFalse(toUser.getIsFreeze(), () -> new GlobalRunTimeException("该用户不存在"));
        Assert.isTrue(toUser.getIsSm(), () -> new GlobalRunTimeException("用户尚未实名认证"));

        userCollection.setGiveStatus(GiveStatusEnum.GIVING);
        userCollection.setGiveTime(DateTime.now());
        userCollection.setIsHold(false);
        userCollection.setToUserId(toUser.getId());
        userCollection.setIsDaoSource(true);
        if (!userCollection.updateById()) {
            throw new GlobalRunTimeException("系统繁忙请稍后再试");
        }
        privilegeService.flushUserLevel(userCollection.getUserId());

        //降级逻辑
        daoService.downgrade(userCollection.getCollectionId(), userCollection.getUserId(), ReceivedCollectionType.GIVE);
        privilegeService.flushUserLevel(userCollection.getUserId());
        collectionGiftLog.setCollectionId(digitalCollection.getId());
        collectionGiftLog.setTitle(digitalCollection.getFirstTitle());
        collectionGiftLog.setNumbering(userCollection.getNumbering());
        collectionGiftLog.setNumberingList(userCollection.getNumbering().toString());
        collectionGiftLog.setConsumeType(collectionGiveDTO.getConsumeType());
        collectionGiftLog.setQuantityConsume("1");
        collectionGiftLog.setAddress(collectionGiveDTO.getAddress());
        collectionGiftLog.setGiftUserId(collectionGiveDTO.getUserInfo().getId());
        collectionGiftLog.setReceiveUserId(collectionGiveDTO.getComplimentarySubscriber().getId());
        collectionGiftLog.setGiftPropIds(Convert.toStr(collectionGiveDTO.getId()));
        collectionGiftLog.setPaymentSum(BigDecimal.valueOf(1));
        collectionGiftLog.insert();
        //添加dao日志
        DaoCollectionGiveLog daoCollectionGiveLog = new DaoCollectionGiveLog();
        daoCollectionGiveLog.setCollectionName(userCollection.getFirstTitle());
        daoCollectionGiveLog.setCollectionId(String.valueOf(userCollection.getCollectionId()));
        daoCollectionGiveLog.setGiveCount(1);
        daoCollectionGiveLog.setGiveUserTel(collectionGiveDTO.getGiftUserTel());
        daoCollectionGiveLog.setReceiveUserTel(collectionGiveDTO.getReceiveUserTel());
        daoCollectionGiveLog.setConsumeCount(1);
        daoCollectionGiveLog.setOperatorId(collectionGiveDTO.getOperatorId());
        daoCollectionGiveLog.insert();

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void collectionBatchGiveDao(CollectionGiveDaoBatchRequest giveDaoBatchRequest) {
        UserInfo user = userInfoDao.getOneByUserTel(giveDaoBatchRequest.getGiftUserTel());
        giveDaoBatchRequest.setUserInfo(user);
        // 最基本的要求 用户是有效用户
        if (!giveDaoBatchRequest.getUserInfo().getIsValid()) {
            throw new GlobalRunTimeException("还未成为有效用户,不能转账哦");
        }
        // 市值账号的判定,如果他是市值账号的话那么把他定义成有效用户
        FilterIncomeList isTeamIncomeByUserId = filterIncomeListDao.getIsTeamIncomeByUserIdAndDaoId(giveDaoBatchRequest.getDaoId(), giveDaoBatchRequest.getUserInfo().getId());
        if (!ObjectUtil.isNull(isTeamIncomeByUserId)) {
            giveDaoBatchRequest.getUserInfo().setIsValid(Boolean.TRUE);
        }
        // 验证要转增的藏品是否存在
        //UserCollection userCollection = userCollectionDao.getById(collectionGiveDTO.getId());
        List<UserCollection> userCollectionList = userCollectionDao.listByIdListAndUserId(giveDaoBatchRequest.getUserInfo().getId(), giveDaoBatchRequest.getIdList());
        if (CollectionUtils.isEmpty(userCollectionList) || userCollectionList.size() != giveDaoBatchRequest.getIdList().size()) {
            throw new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND);
        }
        List<Long> collectionIdList = userCollectionList.stream().map(UserCollection::getCollectionId).distinct().collect(Collectors.toList());
        if (collectionIdList.size() > 1) {
            throw new GlobalRunTimeException(ErrorCode.NOT_SAME_COLLECTION);
        }
        Long collectionId = collectionIdList.get(0);

        UserChainInfo giftUserChainInfo = userChainInfoDao.getByUserId(giveDaoBatchRequest.getUserInfo().getId());
        giveDaoBatchRequest.setGiftUserChainInfo(giftUserChainInfo);


        // 判定转增的时候这个藏品是否存在,因为要知道这个藏品的状态是否是可以转赠的
        DigitalCollection digitalCollection = digitalCollectionDao.getById(collectionId);
        if (BeanUtil.isEmpty(digitalCollection)) {
            throw new GlobalRunTimeException("未找到藏品");
        }
        /*if (!digitalCollection.getIsGive()) {
            throw new GlobalRunTimeException("该藏品无法转增");
        }*/
        //根据接收方手机号 获取用户 以及地址
        UserInfo complimentarySubscriber = userInfoDao.getOneByUserTel(giveDaoBatchRequest.getReceiveUserTel());
        if (Objects.isNull(complimentarySubscriber)) {
            throw new GlobalRunTimeException("未找到此手机号用户");
        }
        List<Long> userBelongingToDao = userCreatorInfoDao.getUserBelongingToDao(complimentarySubscriber.getId());
        if (CollectionUtils.isEmpty(userBelongingToDao) || !userBelongingToDao.contains(giveDaoBatchRequest.getDaoId())) {
            throw new GlobalRunTimeException("接收方非本网体下用户");
        }
        UserChainInfo receiveGiftUserChainInfo = userChainInfoDao.getByUserId(complimentarySubscriber.getId());
        giveDaoBatchRequest.setComplimentarySubscriber(complimentarySubscriber);
        giveDaoBatchRequest.setAddress(receiveGiftUserChainInfo.getAddress());
        if (!giveDaoBatchRequest.selfDenial()) {
            throw new GlobalRunTimeException("赠送人不能是自己");
        }

        // 藏品效验器
        userCollectionList.forEach(userCollection -> {
            verifyCollection(userCollection, giveDaoBatchRequest.getUserInfo());
            if (!userCollection.getIsOpen() && userCollection.getStatus() == ChainStatusEnum.NONE) {
                userCollection.setStatus(ChainStatusEnum.ONLINE);
            }
            if (userCollection.getStatus() != ChainStatusEnum.ONLINE) {
                throw new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_ONLINE);
            }
            if (userCollection.getOnConsign() != CollectionOnConsignEnum.NORMAL) {
                throw new GlobalRunTimeException(ErrorCode.COLLECTION_ON_SIGN);
            }
            // 需要确定他是不是盲盒,如果是盲盒的话要单独做判定
            if (!userCollection.getIsOpen() && userCollection.getBoxId() != null && userCollection.getBoxId() != 0L) {
                BoxProduct boxProduct = boxProductDao.getById(userCollection.getBoxId());
                if (ObjectUtil.isEmpty(boxProduct)) {
                    throw new GlobalRunTimeException(ErrorCode.MALL_PRODUCT_DOES_NOT_EXIST);
                }
                if (!boxProduct.getIsGive()) {
                    throw new GlobalRunTimeException(ErrorCode.THIS_COLLECTION_CANNOT_BE_TRANSFERRED);
                }
            }
        });

        //List<CollectionGift> collectionGifts = collectionGiftDao.getCollectionId(digitalCollection.getId());
        giveDaoBatchRequest.calculate_(giveDaoBatchRequest.getCount(), 1);
        String remark = StrUtil.format("转赠藏品消耗");
        if (giveDaoBatchRequest.getConsumeType() != 2) {
            throw new GlobalRunTimeException("当前不支持该类型转增");
        }
        // 记录扣除所需要的钱或者星球碎片消耗 或者生态燃料
        // 记录用户转增数据日志
        DaoWallet daoWallet = daoWalletDao.getByDaoId(giveDaoBatchRequest.getDaoId());
        if (NumberUtil.isLess(daoWallet.getBalance(), giveDaoBatchRequest.getAmount())) {
            throw new GlobalRunTimeException("余额不足");
        }
        giveDaoBatchRequest.setDaoWallet(daoWallet);
        daoWalletService.subBalance(giveDaoBatchRequest.getDaoId(), null, giveDaoBatchRequest.getAmount(), BigDecimal.ZERO, DaoWalletTypeEnum.COLLECTION_GIVE, remark);
        UserInfo toUser = userInfoDao.getByUUID(complimentarySubscriber.getUserUuid());
        Assert.notNull(toUser, () -> new GlobalRunTimeException(ErrorCode.THE_USER_DOES_NOT_EXIST));
        Assert.isFalse(toUser.getIsFreeze(), () -> new GlobalRunTimeException(ErrorCode.THE_USER_DOES_NOT_EXIST));
        Assert.isTrue(toUser.getIsSm(), () -> new GlobalRunTimeException(ErrorCode.USER_NOT_SM));

        userCollectionList.stream().forEach(userCollection -> {
            userCollection.setGiveStatus(GiveStatusEnum.GIVING);
            userCollection.setGiveTime(DateTime.now());
            userCollection.setIsHold(false);
            userCollection.setToUserId(toUser.getId());
            userCollection.setIsDaoSource(true);
            if (!userCollection.updateById()) {
                throw new GlobalRunTimeException(ErrorCode.THE_SYSTEM_IS_BUSY_PLEASE_TRY_AGAIN_LATER);
            }
        });
        privilegeService.flushUserLevel(giveDaoBatchRequest.getUserInfo().getId());

        //降级逻辑
        daoService.downgrade(collectionId, giveDaoBatchRequest.getUserInfo().getId(), ReceivedCollectionType.GIVE);
        //添加dao日志
        //对collectionIdList进行分页每页二十条
        List<List<UserCollection>> partition = Lists.partition(userCollectionList, 20);
        for (List<UserCollection> values : partition) {
            List<Long> collectId = values.stream().map(UserCollection::getCollectionId).distinct().collect(Collectors.toList());
            String join = StringUtils.join(collectId, ",");
            CollectionGiftLog collectionGiftLog = new CollectionGiftLog();
            collectionGiftLog.setCollectionId(digitalCollection.getId());
            collectionGiftLog.setTitle(digitalCollection.getFirstTitle());
            collectionGiftLog.setNumbering(0);
            collectionGiftLog.setNumberingList(values.stream().map(UserCollection::getNumbering).map(String::valueOf).collect(Collectors.joining(",")));
            collectionGiftLog.setConsumeType(giveDaoBatchRequest.getConsumeType());
            collectionGiftLog.setQuantityConsume(String.valueOf(values.size()));
            collectionGiftLog.setAddress(giveDaoBatchRequest.getAddress());
            collectionGiftLog.setGiftUserId(giveDaoBatchRequest.getUserInfo().getId());
            collectionGiftLog.setReceiveUserId(giveDaoBatchRequest.getComplimentarySubscriber().getId());
            collectionGiftLog.setGiftPropIds(join);
            collectionGiftLog.setPaymentSum(BigDecimal.valueOf(values.size()));
            collectionGiftLog.insert();


            DaoCollectionGiveLog daoCollectionGiveLog = new DaoCollectionGiveLog();
            daoCollectionGiveLog.setCollectionName(digitalCollection.getFirstTitle());
            daoCollectionGiveLog.setCollectionId(join);
            daoCollectionGiveLog.setGiveCount(values.size());
            daoCollectionGiveLog.setGiveUserTel(giveDaoBatchRequest.getGiftUserTel());
            daoCollectionGiveLog.setReceiveUserTel(giveDaoBatchRequest.getReceiveUserTel());
            daoCollectionGiveLog.setConsumeCount(values.size());
            daoCollectionGiveLog.setOperatorId(giveDaoBatchRequest.getOperatorId());
            daoCollectionGiveLog.insert();
        }

    }

    @Override
    public List<HoldPropVO> holdProp(String propName) {
        //获取所有的道具集合
        List<HoldPropDataVO> equityPropsList = userEquityPropsService.holdProp(UserPool.getUser().getId(), propName);
        ArrayList<HoldPropVO> holdPropVOArrayList = new ArrayList<>();
        Map<Long, List<HoldPropDataVO>> collect = equityPropsList.stream().collect(Collectors.groupingBy(HoldPropDataVO::getEquityPropsId));
        collect.forEach((key, values) -> {
            //持仓数量
            Integer positionNum = values.size();
            //成本价
            BigDecimal cost = values.stream().map(HoldPropDataVO::getProductPrice).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_DOWN);
            // 市价 该藏品 最新成交价
            BigDecimal marketPrice = values.get(0).getNewDeal();
            // 市值 该藏品 最新成交价*持仓数量
            BigDecimal marketValue = marketPrice.multiply(Convert.toBigDecimal(positionNum));
            // 盈亏 当前市值-总买入金额
            BigDecimal profitLoss = marketValue.subtract(cost);
            //盈亏率 盈亏/总买入金额 %
            BigDecimal profitLossRate = BigDecimal.ZERO;
            if (cost.compareTo(Convert.toBigDecimal(0)) == 0 || cost.compareTo(Convert.toBigDecimal(0)) == -1) {
                profitLossRate = new BigDecimal("0.00");
            } else {
                profitLossRate = profitLoss.divide(cost, 4, BigDecimal.ROUND_DOWN).multiply(Convert.toBigDecimal(100)).setScale(2, BigDecimal.ROUND_DOWN);
            }
            HoldPropVO holdPropVO = new HoldPropVO();
            //道具名称
            holdPropVO.setEquityPropName(values.get(0).getFirstTitle());
            //道具Id
            holdPropVO.setEquityPropsId(values.get(0).getEquityPropsId());
            //道具持仓数量
            holdPropVO.setPositionNum(positionNum);
            //道具成本
            holdPropVO.setCost(Convert.toStr(cost.divide(Convert.toBigDecimal(values.size()), 2, BigDecimal.ROUND_DOWN)));
            //道具市价
            holdPropVO.setMarketPrice(Convert.toStr(marketPrice));
            //道具市值
            holdPropVO.setMarketValue(Convert.toStr(marketValue));
            //道具盈亏
            holdPropVO.setProfitLoss(Convert.toStr(profitLoss));
            //道具盈亏率
            holdPropVO.setProfitLossRate(Convert.toStr(profitLossRate));
            //道具缩略图
            holdPropVO.setCreationContent(values.get(0).getCreationContent());
            holdPropVOArrayList.add(holdPropVO);
        });
        return holdPropVOArrayList;
    }

    @Override
    public SingleHoldEquityProp singleHoldEquityProp(Long id) {
        //获取用户拥有的道具集合 按照分页查询结果
        List<HoldPropDataVO> holdPropDataVO = userEquityPropsService.getSingleHoldEquityPropDataByUserIdAndEquityPropId(UserPool.getUser().getId(), id);
        SingleHoldEquityProp singleHoldEquityProp = new SingleHoldEquityProp();
        if (ObjectUtil.isNull(holdPropDataVO) || holdPropDataVO.size() == 0) {
            return singleHoldEquityProp;
        }

        //持仓市值
        BigDecimal marketValue = holdPropDataVO.get(0).getNewDeal().multiply(Convert.toBigDecimal(holdPropDataVO.size()));
        singleHoldEquityProp.setMarketValue(Convert.toStr(marketValue));
        //道具名称
        singleHoldEquityProp.setEquityPropName(holdPropDataVO.get(0).getFirstTitle());
        //最新成交价
        singleHoldEquityProp.setNewDeal(Convert.toStr(holdPropDataVO.get(0).getNewDeal()));
        // 获取昨天该商品最后一笔的成交价.如果是空的话,最新成交价就是0. 计算公式:(最新成交价-昨日最后成交价)/昨日最后成交价
        SecondEquityPropsOrder secondEquityPropsOrder = secondEquityPropsOrderDao.selectByRelationIdSubOneDayData(id);
        // 昨日最后成交价
        BigDecimal finishingStroke = BigDecimal.ZERO;
        //如果昨日最后成交价不存在 需要一个默认价位（今日涨幅为100%）
        if (!BeanUtil.isEmpty(secondEquityPropsOrder)) {
            finishingStroke = secondEquityPropsOrder.getBuyPrice();
        }
        //缩略图
        singleHoldEquityProp.setCreationContent(holdPropDataVO.get(0).getCreationContent());
        //计算今日涨幅
        if (finishingStroke.compareTo(BigDecimal.ZERO) == 0 || finishingStroke.compareTo(BigDecimal.ZERO) == -1) {
            singleHoldEquityProp.setToDaysGains(Convert.toStr(new BigDecimal("0.00")));
        } else {
            BigDecimal toDaysGains = (holdPropDataVO.get(0).getNewDeal().subtract(finishingStroke)).divide(finishingStroke, 4, BigDecimal.ROUND_HALF_UP).multiply(Convert.toBigDecimal(100)).setScale(2, BigDecimal.ROUND_DOWN);
            singleHoldEquityProp.setToDaysGains(Convert.toStr(toDaysGains));
        }
        return singleHoldEquityProp;
    }

    @Override
    public Page<SingleHoldEquityPropDetails> singleHoldEquityPropDetailsPage(Integer pageNo, Integer pageSize, Long
            id) {
        //获取用户拥有的道具集合 按照分页查询结果
        Page<HoldPropDataVO> holdPropDataVOPage = userEquityPropsService.getSingleHoldEquityPropData(UserPool.getUser().getId(), pageNo, pageSize, id);
        List<HoldPropDataVO> holdPropDataVOList = holdPropDataVOPage.getRecords();
        Page<SingleHoldEquityPropDetails> singleHoldEquityPropVOPage = new Page<SingleHoldEquityPropDetails>();
        if (ObjectUtil.isNull(holdPropDataVOList) || holdPropDataVOList.size() == 0) {
            return singleHoldEquityPropVOPage;
        }

        List<SingleHoldEquityPropDetails> singleHoldEquityPropDetailsList = new ArrayList<>();
        for (HoldPropDataVO holdPropDataVO : holdPropDataVOList) {
            SingleHoldEquityPropDetails singleHoldEquityPropDetails = new SingleHoldEquityPropDetails();
            singleHoldEquityPropDetails.setCost(Convert.toStr(holdPropDataVO.getProductPrice().setScale(2, BigDecimal.ROUND_HALF_UP)));
            singleHoldEquityPropDetails.setEquityPropsId(Convert.toStr(holdPropDataVO.getEquityPropsId()));
            //盈亏 =  最新成交价 - 购买价
            singleHoldEquityPropDetails.setProfitLoss(Convert.toStr(holdPropDataVO.getNewDeal().subtract(holdPropDataVO.getProductPrice())));
            //盈亏率
            if (holdPropDataVO.getProductPrice().compareTo(BigDecimal.ZERO) == 0 || holdPropDataVO.getProductPrice().compareTo(BigDecimal.ZERO) == -1) {
                singleHoldEquityPropDetails.setProfitLossRate(Convert.toStr(new BigDecimal("0.00")));
            } else {
                singleHoldEquityPropDetails.setProfitLossRate(Convert.toStr((holdPropDataVO.getNewDeal().subtract(holdPropDataVO.getProductPrice())).divide(holdPropDataVO.getProductPrice(), 4, BigDecimal.ROUND_HALF_UP).multiply(Convert.toBigDecimal(100)).setScale(2, BigDecimal.ROUND_DOWN)));
            }
            singleHoldEquityPropDetailsList.add(singleHoldEquityPropDetails);
        }

        singleHoldEquityPropVOPage.setRecords(singleHoldEquityPropDetailsList);
        singleHoldEquityPropVOPage.setTotal(holdPropDataVOPage.getTotal());
        singleHoldEquityPropVOPage.setSize(holdPropDataVOPage.getSize());
        singleHoldEquityPropVOPage.setCurrent(holdPropDataVOPage.getCurrent());
        return singleHoldEquityPropVOPage;
    }

    @Override
    public BatchGiveMetaWalletDetailsVO batchGiveMetaWalletDetails(UserInfo user, Long collectionId) {

        DigitalCollection collection = digitalCollectionDao.getCollectionByIdAndIsGiveImeta(collectionId, Boolean.TRUE);
        Assert.notNull(collection, () -> new GlobalRunTimeException("此藏品暂未开启跨链转增"));


        BatchGiveMetaWalletDetailsVO batchGiveMetaWalletDetailsVO = new BatchGiveMetaWalletDetailsVO();
        batchGiveMetaWalletDetailsVO.setNewDeal(collection.getNewDeal());
        batchGiveMetaWalletDetailsVO.setCreationContent(collection.getCreationContent());
        batchGiveMetaWalletDetailsVO.setCollectionName(collection.getFirstTitle());

        CollecionLinkContrastRecords contrastRecords = collecionLinkContrastRecordsDao.getOneByCollectionId(collectionId);
        Assert.notNull(contrastRecords, () -> new GlobalRunTimeException("此藏品暂未开启跨链转增"));

        batchGiveMetaWalletDetailsVO.setGiveDetailsVOList(userCollectionDao.getBatchGiveMetaWalletDetails(user.getId(), collectionId));
        batchGiveMetaWalletDetailsVO.setCrossChainGiveDesc(staticDataDao.getByType("cross_chain_give_desc").getValue());
        return batchGiveMetaWalletDetailsVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void giveMetaWallet(String userAddr, Integer consumeType, Long
            collectionId, List<Long> userCollectionIds, UserInfo user) throws IllegalAccessException {

        DigitalCollection collection = digitalCollectionDao.getById(collectionId);
        Assert.notNull(collection, () -> new GlobalRunTimeException("藏品不存在"));
        Assert.isTrue(collection.getIsGiveImeta(), () -> new GlobalRunTimeException("此藏品暂未开启跨链转增"));

        MetaWalletCrossUserVO metaWalletCrossUserVO = metaWalletService.checkUeerArrd(userAddr);

        CollecionLinkContrastRecords contrastRecords = collecionLinkContrastRecordsDao.getOneByCollectionId(collectionId);
        Assert.notNull(contrastRecords, () -> new GlobalRunTimeException("此藏品暂未开启跨链转增"));

        List<SecondCollectionConfig> brandIncubationList = secondCollectionConfigDao.getListByStatusAndMarketType(MarketTypeEnum.BRAND_INCUBATION);
        List<Long> secondCollectionIds = brandIncubationList.stream().map(SecondCollectionConfig::getId).collect(Collectors.toList());

        List<UserCollection> userCollectionList = userCollectionDao.getGiveListByCollectionIdAndUserCollectionIds(user.getId(), collectionId, userCollectionIds, secondCollectionIds);
        Assert.isTrue(userCollectionList.size() == userCollectionIds.size(), () -> new GlobalRunTimeException("存在不符合转增的藏品"));

        //编号集合
        List<Integer> collect = userCollectionList.stream().map(UserCollection::getNumbering).collect(Collectors.toList());
        Assert.isTrue(metaWalletService.checkCollectionNumerber(user, contrastRecords.getCollectionId(), collect, userAddr), () -> new GlobalRunTimeException("存在不符合转增的藏品"));

        //获取消耗明细
        CollectionGift collectionGift = collectionGiftDao.getConfListByCollectionIdAndTypeAnd(collectionId, CollectionOriginalTypeEnum.MATE_WALLET, consumeType);
        //单价 * 数量 = 总价
        BigDecimal sum = Convert.toBigDecimal(collectionGift.getQuantityConsume()).multiply(Convert.toBigDecimal(userCollectionIds.size()));
        collectionGift.setQuantityConsume(sum.setScale(2, BigDecimal.ROUND_DOWN).toPlainString());
        CollectionGiftLog collectionGiftLog = new CollectionGiftLog();
        //扣款
        if (consumeType.equals(1)) {//积分
            userAssetsService.subIntegralByUserId(sum, user.getId(), CoinCategoryEnum.INTEGRAL, AssetChangeLogEnum.GIVE_MATE_WALLET, 0L, StrUtil.format("跨链转赠{}藏品消耗", collection.getFirstTitle()));
        } else if (consumeType.equals(2)) {//扣余额
            UserWallet userWallet = userWalletService.getByUserId(user.getId());
            if (NumberUtil.isLess(userWallet.getBalance().add(userWallet.getPayBalance()), sum)) {
                throw new GlobalRunTimeException("余额不足");
            }
            BigDecimal payBalance = userWallet.getPayBalance();
            // 扣钱.
            //1.先扣支付余额 2.再扣提现余额
            if (payBalance.compareTo(sum) >= 0) { //如果支付账户足够 直接从支付账户扣
                Assert.isTrue(userWalletService.subBalance(userWallet, sum, 0L, WalletDetailTypeEnum.GIVE_MATE_WALLET, UserBalanceTypeEnum.PAY_BALANCE, StrUtil.format("跨链转赠{}藏品消耗", collection.getFirstTitle())), () -> new GlobalRunTimeException(ErrorCode.PAYMENT_FAILED));
            } else {//如果支付账户没钱
                if (payBalance.compareTo(BigDecimal.ZERO) == 0) {//支付账户没钱,直接扣提现账户
                    Assert.isTrue(userWalletService.subBalance(userWallet, sum, 0L, WalletDetailTypeEnum.GIVE_MATE_WALLET, UserBalanceTypeEnum.BALANCE, StrUtil.format("跨链转赠{}藏品消耗", collection.getFirstTitle())), () -> new GlobalRunTimeException(ErrorCode.PAYMENT_FAILED));
                } else {//如果支付账户有钱 但是不够
                    //先扣除支付账户
                    Assert.isTrue(userWalletService.subBalance(userWallet, payBalance, 0L, WalletDetailTypeEnum.GIVE_MATE_WALLET, UserBalanceTypeEnum.PAY_BALANCE, StrUtil.format("跨链转赠{}藏品消耗", collection.getFirstTitle())), () -> new GlobalRunTimeException(ErrorCode.PAYMENT_FAILED));
                    BigDecimal subtract = sum.subtract(payBalance);
                    Assert.isTrue(userWalletService.subBalance(userWallet, subtract, 0L, WalletDetailTypeEnum.GIVE_MATE_WALLET, UserBalanceTypeEnum.BALANCE, StrUtil.format("跨链转赠{}藏品消耗", collection.getFirstTitle())), () -> new GlobalRunTimeException(ErrorCode.PAYMENT_FAILED));
                }
            }
        } else {
            //生态燃料扣除
            UserEcologyPoints userEcologyPoints = userEcologyPointsService.getOneByUserId(user.getId());
            if (NumberUtil.isGreater(userEcologyPoints.getAmount(), userEcologyPoints.getAmount())) {
                throw new GlobalRunTimeException("生态燃料不足");
            }
            Assert.isTrue(userEcologyPointsService.subAmount(user.getId(), sum, EcologyPointsEnum.GIFT_PROPS, StrUtil.format("转赠{}藏品消耗", StrUtil.format("跨链转赠{}藏品消耗", collection.getFirstTitle()), collection.getFirstTitle())), () -> new GlobalRunTimeException("扣除生态燃料失败"));
        }

        UserChainInfo userChainInfo = userChainInfoDao.getByUserId(user.getId());
        //修改持有状态和插入链日志
        for (UserCollection userCollection : userCollectionList) {
            Assert.isTrue(userCollectionDao.giveMetaWallet(userCollection.getId()), () -> new GlobalRunTimeException("转增失败"));

            UserCollectionChainLog userCollectionChainLog = new UserCollectionChainLog();

            UserCollectionChainLog oldUserCollectionChainLog = userCollectionChainLogDao.getOneByUserIdAndUserCollectionId(userCollection.getUserId(), userCollection.getId());
            userCollectionChainLog.setUserId(userCollection.getUserId());
            userCollectionChainLog.setDaoId(oldUserCollectionChainLog.getDaoId());
            userCollectionChainLog.setUserCollectionId(userCollection.getId());
            userCollectionChainLog.setCollectionType(ReceivedCollectionType.TRANSFER_TO_META_WALLET);
            userCollectionChainLog.setType(UserChainTypeEnum.TO_META_WALLET);
            userCollectionChainLog.setStatus(UserChainLogStatusEnum.WAIT);
            userCollectionChainLog.setCollectionId(userCollection.getCollectionId());
            userCollectionChainLog.setContractAddress(oldUserCollectionChainLog.getContractAddress());
            userCollectionChainLog.setDeployTransactionHash(oldUserCollectionChainLog.getDeployTransactionHash());
            //转增到系统地址
            UserChainInfo toUserChain = userChainInfoDao.getByUserId(1L);
            userCollectionChainLog.setAddress(toUserChain.getAddress());
            userCollectionChainLog.setTokenId(oldUserCollectionChainLog.getTokenId());
            userCollectionChainLog.setFromUserId(userCollection.getUserId());
            userCollectionChainLog.setFromUserCollectionId(userCollection.getId());
            userCollectionChainLog.setFromUserAddress(userChainInfo.getAddress());
            userCollectionChainLog.setToUserId(1L);
            userCollectionChainLog.setToUserAddress(metaWalletCrossUserVO.getUserAddr());
            userCollectionChainLog.insert();

            TransferCollectionWithoutRecords transferCollectionWithoutRecords = new TransferCollectionWithoutRecords();
            transferCollectionWithoutRecords.setType(CollectionOriginalTypeEnum.MATE_WALLET);
            transferCollectionWithoutRecords.setUserId(user.getId());
            transferCollectionWithoutRecords.setUserCollectionId(userCollection.getUserId());
            transferCollectionWithoutRecords.setCollectionId(userCollection.getCollectionId());
            transferCollectionWithoutRecords.setTokenId(oldUserCollectionChainLog.getTokenId());
            transferCollectionWithoutRecords.setToUserAddr(userAddr);
            transferCollectionWithoutRecords.setStatus(TransferCollectionWithoutStatusEnum.WAITING);
            transferCollectionWithoutRecords.setContractAddress(oldUserCollectionChainLog.getContractAddress());
            transferCollectionWithoutRecords.setUserCollectionChainLogId(userCollectionChainLog.getId());
            transferCollectionWithoutRecords.setFromUserAddr(userChainInfo.getAddress());
            transferCollectionWithoutRecords.setFromUserNickName(user.getNickName());
            transferCollectionWithoutRecords.insert();
        }
        //刷新权益
        privilegeService.flushUserLevel(user.getId());
        //降级逻辑
        daoService.downgrade(collectionId, user.getId(), ReceivedCollectionType.GIVE);

        //转增日志
        collectionGiftLog.setGiveType(CollectionOriginalTypeEnum.MATE_WALLET);
        collectionGiftLog.setPaymentSum(sum);
        collectionGiftLog.setCollectionId(collectionId);
        collectionGiftLog.setTitle(collection.getFirstTitle());
        collectionGiftLog.setNumbering(0);
        collectionGiftLog.setNumberingList(collect.stream().map(String::valueOf).collect(Collectors.joining(",")));
        collectionGiftLog.setConsumeType(consumeType);
        collectionGiftLog.setQuantityConsume(StrUtil.toString(userCollectionIds.size()));
        collectionGiftLog.setAddress(userAddr);
        collectionGiftLog.setGiftUserId(user.getId());
        collectionGiftLog.setReceiveUserId(1L);
        collectionGiftLog.setGiftPropIds(StrUtil.EMPTY);
        //todo 钱包接口提供
        collectionGiftLog.setToUserAddr(userAddr);
        collectionGiftLog.setToUserNickName(metaWalletCrossUserVO.getNickname());
        collectionGiftLog.setFromUserAddr(userChainInfo.getAddress());
        collectionGiftLog.setFromUserNickName(user.getNickName());
        collectionGiftLog.insert();
    }


    @Override
    public Boolean updateFreezingStatusById(Long id, UserCollectionFreezingStatusEnum freezingStatus) {
        return userCollectionDao.updateFreezingStatusById(id, freezingStatus);
    }

    @Override
    public Boolean updateFreezingStatusByIds(List<Long> ids, UserCollectionFreezingStatusEnum freezingStatus) {
        return userCollectionDao.updateFreezingStatusByIds(ids, freezingStatus);
    }

    @Override
    public Boolean whetherTheUserOwnsACollection(Long userId, Long collectionId) {
        return userCollectionDao.whetherTheUserOwnsACollection(userId, collectionId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void recoverCollections(List<UserCollection> userCollectionList) {
        UserChainInfo userChainInfo = userChainInfoDao.getRegisterByUserId(1L);
        int count = 0;
        for (UserCollection userCollection : userCollectionList) {
            log.info("开始回收,总数:{},当前数量:{}", userCollectionList.size(), count++);
            //标记藏品为回收状态 并且当前用户未持有
            Assert.isTrue(userCollectionDao.recoverCollectionById(userCollection.getId(), userChainInfo.getUserId()), () -> new GlobalRunTimeException(ErrorCode.THE_SYSTEM_IS_BUSY_PLEASE_TRY_AGAIN_LATER));
            privilegeService.flushUserLevel(userCollection.getUserId());
            //降级逻辑
            daoService.downgrade(userCollection.getCollectionId(), userCollection.getUserId(), ReceivedCollectionType.GIVE);


            UserCollectionChainLog formUserChainLogInfo = userCollectionChainLogDao.getOneByUserIdAndUserCollectionId(userCollection.getUserId(), userCollection.getId());

            UserCollectionChainLog userCollectionChainLog = new UserCollectionChainLog();
            userCollectionChainLog.setUserId(userCollection.getUserId());
            userCollectionChainLog.setDaoId(0L);
            userCollectionChainLog.setUserCollectionId(userCollection.getId());
            userCollectionChainLog.setCollectionType(ReceivedCollectionType.RECYCLE);
            userCollectionChainLog.setType(UserChainTypeEnum.RECYCLE);
            userCollectionChainLog.setStatus(UserChainLogStatusEnum.WAIT);
            userCollectionChainLog.setCollectionId(userCollection.getCollectionId());
            userCollectionChainLog.setContractAddress(formUserChainLogInfo.getContractAddress());
            userCollectionChainLog.setDeployTransactionHash(formUserChainLogInfo.getTransactionHash());
            userCollectionChainLog.setProductId(formUserChainLogInfo.getProductId());
            userCollectionChainLog.setAddress(formUserChainLogInfo.getAddress());
            userCollectionChainLog.setTokenId(formUserChainLogInfo.getTokenId());
            userCollectionChainLog.setFromUserId(userCollection.getUserId());
            userCollectionChainLog.setFromUserCollectionId(userCollection.getId());
            userCollectionChainLog.setFromUserAddress(formUserChainLogInfo.getToUserAddress());
            userCollectionChainLog.setToUserId(1L);
            userCollectionChainLog.setToUserCollectionId(0L);
            userCollectionChainLog.setToUserAddress(userChainInfo.getAddress());
            userCollectionChainLog.setCollectionChainId(0L);
            userCollectionChainLog.insert();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void temporarilyRecoverCollections(List<UserCollection> userCollectionList) {
        UserChainInfo userChainInfo = userChainInfoDao.getRegisterByUserId(1L);
        int count = 0;
        for (UserCollection userCollection : userCollectionList) {
            log.info("开始回收,总数:{},当前数量:{}", userCollectionList.size(), count++);
            //标记藏品为回收状态 并且当前用户未持有
            Assert.isTrue(userCollectionDao.temporarilyRecoverCollectionById(userCollection.getId(), userChainInfo.getUserId()), () -> new GlobalRunTimeException(ErrorCode.THE_SYSTEM_IS_BUSY_PLEASE_TRY_AGAIN_LATER));

            UserCollectionChainLog formUserChainLogInfo = userCollectionChainLogDao.getOneByUserIdAndUserCollectionId(userCollection.getUserId(), userCollection.getId());

            UserCollectionChainLog userCollectionChainLog = new UserCollectionChainLog();
            userCollectionChainLog.setUserId(userCollection.getUserId());
            userCollectionChainLog.setDaoId(0L);
            userCollectionChainLog.setUserCollectionId(userCollection.getId());
            userCollectionChainLog.setCollectionType(ReceivedCollectionType.RECYCLE);
            userCollectionChainLog.setType(UserChainTypeEnum.RECYCLE);
            userCollectionChainLog.setStatus(UserChainLogStatusEnum.WAIT);
            userCollectionChainLog.setCollectionId(userCollection.getCollectionId());
            userCollectionChainLog.setContractAddress(formUserChainLogInfo.getContractAddress());
            userCollectionChainLog.setDeployTransactionHash(formUserChainLogInfo.getTransactionHash());
            userCollectionChainLog.setProductId(formUserChainLogInfo.getProductId());
            userCollectionChainLog.setAddress(formUserChainLogInfo.getAddress());
            userCollectionChainLog.setTokenId(formUserChainLogInfo.getTokenId());
            userCollectionChainLog.setFromUserId(userCollection.getUserId());
            userCollectionChainLog.setFromUserCollectionId(userCollection.getId());
            userCollectionChainLog.setFromUserAddress(formUserChainLogInfo.getToUserAddress());
            userCollectionChainLog.setToUserId(1L);
            userCollectionChainLog.setToUserCollectionId(0L);
            userCollectionChainLog.setToUserAddress(userChainInfo.getAddress());
            userCollectionChainLog.setCollectionChainId(0L);
            userCollectionChainLog.insert();
        }
    }

    @Override
    public Boolean getIsHoldCollection(Long userId, List<Long> collectionIds) {
        Integer count = userCollectionDao.getUserHoldCollectionByIds(userId, collectionIds);
        return count > 0;
    }

    @Override
    public List<Long> getUserListByCollectionIds(List<Long> collectionIds) {
        if (collectionIds.size() == 0) {
            return Lists.newArrayList();
        }
        return userCollectionDao.getUserListByCollectionIds(collectionIds);
    }


    @Override
    public List<Long> getJuniorHoldCollectionCountByCollectionIds(Long userId, List<Long> collectionIds) {
        return userCollectionDao.getJuniorHoldCollectionCountByCollectionIds(userId, collectionIds);
    }


    @Override
    public Integer getHoldCountByCollectionIdsAndUserId(Long userId, List<Long> collectionIds) {
        if (collectionIds.size() == 0) {
            return 0;
        }

        List<UserHoldCollectionDTO> list = userCollectionDao.getHoldCountByCollectionIdsAndUserId(userId, collectionIds);
        if (list.size() == 0) {
            return 0;
        }

        return list.stream().mapToInt(o -> Objects.isNull(o.getHoldCount()) ? 0 : o.getHoldCount()).sum();
    }


    /**
     * 查询用户持有的数量
     *
     * @param userIdList
     * @param collectionIds
     * @return
     */
    @Override
    public List<UserHoldCollectionDTO> getHoldCountByCollectionIdsAndUserIdList(List<Long> userIdList, List<Long> collectionIds) {
        if (CollectionUtils.isEmpty(userIdList) || CollectionUtils.isEmpty(collectionIds)) {
            return null;
        }
        return userCollectionDao.getHoldCountByCollectionIdsAndUserIdList(userIdList, collectionIds);
    }

    @Override
    public void ecologyDestroyCollections(List<UserCollection> userCollectionList) {
        UserChainInfo userChainInfo = userChainInfoDao.getRegisterByUserId(1L);
        int count = 0;
        for (UserCollection userCollection : userCollectionList) {
            log.info("开始回收,总数:{},当前数量:{}", userCollectionList.size(), count++);
            //标记藏品为回收状态 并且当前用户未持有
            Assert.isTrue(userCollectionDao.ecologyDestroyCollections(userCollection.getId()), () -> new GlobalRunTimeException(ErrorCode.THE_SYSTEM_IS_BUSY_PLEASE_TRY_AGAIN_LATER));
            privilegeService.flushUserLevel(userCollection.getUserId());
            //降级逻辑
            daoService.downgrade(userCollection.getCollectionId(), userCollection.getUserId(), ReceivedCollectionType.GIVE);


            UserCollectionChainLog formUserChainLogInfo = userCollectionChainLogDao.getOneByUserIdAndUserCollectionId(userCollection.getUserId(), userCollection.getId());

            UserCollectionChainLog userCollectionChainLog = new UserCollectionChainLog();
            userCollectionChainLog.setUserId(userCollection.getUserId());
            userCollectionChainLog.setDaoId(0L);
            userCollectionChainLog.setUserCollectionId(userCollection.getId());
            userCollectionChainLog.setCollectionType(ReceivedCollectionType.ECOLOGY_DESTROY);
            userCollectionChainLog.setType(UserChainTypeEnum.ECOLOGY_DESTROY);
            userCollectionChainLog.setStatus(UserChainLogStatusEnum.WAIT);
            userCollectionChainLog.setCollectionId(userCollection.getCollectionId());
            userCollectionChainLog.setContractAddress(formUserChainLogInfo.getContractAddress());
            userCollectionChainLog.setDeployTransactionHash(formUserChainLogInfo.getTransactionHash());
            userCollectionChainLog.setProductId(formUserChainLogInfo.getProductId());
            userCollectionChainLog.setAddress(formUserChainLogInfo.getAddress());
            userCollectionChainLog.setTokenId(formUserChainLogInfo.getTokenId());
            userCollectionChainLog.setFromUserId(userCollection.getUserId());
            userCollectionChainLog.setFromUserCollectionId(userCollection.getId());
            userCollectionChainLog.setFromUserAddress(formUserChainLogInfo.getToUserAddress());
            userCollectionChainLog.setToUserId(0L);
            userCollectionChainLog.setToUserCollectionId(0L);
            userCollectionChainLog.setToUserAddress(userChainInfo.getAddress());
            userCollectionChainLog.setCollectionChainId(0L);
            userCollectionChainLog.insert();
        }
    }

    @Override
    public List<TeamHoldCollectionVO> getTeamHoldCollectioncCountByCollectionId(Long collectionId, String userTel) {
        return userCollectionDao.getTeamHoldCollectioncCountByCollectionId(collectionId, userTel);
    }

    @Override
    public Boolean exportDaoTeamHoldCollection(Long daoId, Long daoUserId, String userTel, Long collectionId) {
        Integer holdCount = userCollectionDao.daoTeamHoldCollectionCount(daoUserId, collectionId, userTel);
        Assert.isTrue(holdCount > 0, () -> new GlobalRunTimeException("伞下持仓数量为0"));
        //增加导出记录
        ExportRecords exportRecords = new ExportRecords();
        StringBuilder exportName = new StringBuilder();
        exportName.append(ExportTypeEnum.TEMP_DAO_HOLD_COLLECTION.getName()).append(DateUtil.format(DateUtil.date(), "yyyy年MM月dd日")).append(".xlsx");
        exportRecords.setExportName(exportName.toString());
        exportRecords.setExportType(ExportTypeEnum.TEMP_DAO_HOLD_COLLECTION.getCode());
        exportRecords.setStatus(ExportTypeStatusEnum.EXPORT_STATUS_IN.getCode());
        exportRecords.setDaoId(daoId);
        exportRecords.setType(ExportRecordsTypeEnum.COMMERCIAL);
        if (!exportRecordsDao.save(exportRecords)) {
            throw new GlobalRunTimeException(ErrorCode.OPERATE_FAIL);
        }

        Long exportRecordsId = exportRecords.getId();

        DaoTeamHoldCollectionDTO daoTeamHoldCollectionDTO = new DaoTeamHoldCollectionDTO();
        daoTeamHoldCollectionDTO.setExportRecordsId(exportRecordsId);
        daoTeamHoldCollectionDTO.setDaoUserId(daoUserId);
        daoTeamHoldCollectionDTO.setUserTel(userTel);
        daoTeamHoldCollectionDTO.setCollectionId(collectionId);
        messageQueueHelper.sendMessage(MessageTopic.DAO_TEAM_HOLD_COLLECTION, daoTeamHoldCollectionDTO, MessageTopic.DAO_TEAM_HOLD_COLLECTION, String.valueOf(exportRecordsId));

        return Boolean.TRUE;
    }

    @Override
    public List<DaoTeamHoldCollectionVO> downloadDaoTeamHoldCollection(Long id) {
        List<TempDaoUserCollectionHold> tempDaoUserCollectionHoldList = tempDaoUserCollectionHoldDao.listByExportRecord(id);
        if (CollectionUtil.isEmpty(tempDaoUserCollectionHoldList)) {
            return Collections.emptyList();
        }
        return tempDaoUserCollectionHoldList.stream().map(v -> {
            DaoTeamHoldCollectionVO daoTeamHoldCollectionVO = new DaoTeamHoldCollectionVO();
            daoTeamHoldCollectionVO.setUserTel(v.getUserTel());
            daoTeamHoldCollectionVO.setNickName(v.getNickName());
            daoTeamHoldCollectionVO.setCollectionName(v.getCollectionName());
            daoTeamHoldCollectionVO.setHoldCount(v.getHoldCount());
            return daoTeamHoldCollectionVO;
        }).collect(Collectors.toList());
    }

    @Override
    public IPage<MyBoxTransferVO> myBoxTransfer(Long userId, Integer pageNo, Integer pageSize) {
        return userCollectionDao.myBoxTransfer(userId, pageNo, pageSize);
    }

    @Override
    public IPage<MyBoxReceiveVO> myBoxReceive(Long userId, Integer pageNo, Integer pageSize) {
        return userCollectionDao.myBoxReceive(userId, pageNo, pageSize);
    }

    @Override
    public IPage<BoxGroupVO> boxGroupUser(Long userId, Integer pageNo, Integer pageSize) {
        Page<BoxGroupVO> page = userCollectionDao.boxGroupUser(userId, pageNo, pageSize);
        page.getRecords().forEach(boxGroupVO -> {
            // 循环获取dao名字，dao的图片
            UserCreatorInfo byIdCash = userCreatorInfoDao.getByIdCash(boxGroupVO.getUserCreatorId());
            if (BeanUtil.isNotEmpty(byIdCash)) {
                boxGroupVO.setUserCreatorName(byIdCash.getDaoName());
                boxGroupVO.setUserCreatorImg(byIdCash.getCreatorAvatarImg());
            }
        });
        return page;
    }

    /**
     * 获取用户系列盲盒列表
     *
     * @param boxGroupListDTO
     * @param user
     * @return
     */
    @Override
    public IPage<BoxGroupListVO> boxGroupList(BoxGroupListDTO boxGroupListDTO, UserInfo user) {
        return userCollectionDao.boxGroupList(boxGroupListDTO, user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchGive(UserInfo user, GiveBatchDTO giveBatchDTO) {
        for (Long l : giveBatchDTO.getList()) {
            give(user, giveBatchDTO.getFromAddress(), l);
        }
    }

    @Override
    public GiveRequiredIntegralVO giveRequiredIntegral(UserInfo user, GiveRequiredIntegralDTO
            giveRequiredIntegralDTO) {
        GiveRequiredIntegralVO giveRequiredIntegralVO = new GiveRequiredIntegralVO();
        String giveFeeString = staticDataDao.getByType("give_fee").getValue();
        giveRequiredIntegralVO.setNeedIntegral(Convert.toBigDecimal(giveFeeString).multiply(Convert.toBigDecimal(giveRequiredIntegralDTO.getSum())));
        UserAssets userAssets = userAssetsDao.getByUserIdAndCoinId(user.getId(), CoinCategoryEnum.INTEGRAL.getCode());
        giveRequiredIntegralVO.setHaveIntegral(userAssets.getTokenNum());
        String transferRules = staticDataDao.getByType("transfer_rules").getValue();
        giveRequiredIntegralVO.setTransferRules(transferRules);
        return giveRequiredIntegralVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void generateCollectionNumber(UserCollection userCollection) {
        // 获取全部的已售的订单编号
        List<UserCollection> byCollectionId = userCollectionDao.getByCollectionId(userCollection.getCollectionId());
        // 获取指定的藏品数据
        DigitalCollection byId = digitalCollectionDao.getById(userCollection.getCollectionId());
        // 总数量
        Integer sumCount = byId.getSumCount();
        // 存储总库存数
        List<Integer> allSumCountNumber = new ArrayList<>();
        // 库存编号有1-总数进行初始化
        for (int i = 1; i < sumCount + 1; i++) {
            allSumCountNumber.add(i);
        }
        // 把所有已售的订单编号进行汇总,获取该商品总数,把总数加载到集合中,排除汇总订单编号,把长度进行随机,让后进行get获取,即为新的编号
        List<Integer> collect = byCollectionId.stream().map(UserCollection::getNumbering).collect(Collectors.toList());
        // 获取差集
        allSumCountNumber.removeAll(collect);
        // 根据差集的数量,进行随机数处理.
        if (allSumCountNumber.size() > 1) {
            // 防止随机数的时候左闭右开的场景两个数一致
            int i = RandomUtil.randomInt(0, allSumCountNumber.size());
            userCollectionDao.updateNumbering(userCollection.getId(), allSumCountNumber.get(i));
        } else {
            // 如果是最后一个的话直接获取赋值就可以
            userCollectionDao.updateNumbering(userCollection.getId(), allSumCountNumber.get(0));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchUpdateNumbering(List<UserCollection> userCollections) {
        for (UserCollection userCollection : userCollections) {
            userCollectionDao.updateNumbering(userCollection.getId(), userCollection.getNumbering());
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized void initializationCollectionNumber() {
        List<UserCollection> list = userCollectionDao.getInitializationNumbering();
        for (UserCollection userCollection : list) {
            DigitalCollection digitalCollection = digitalCollectionDao.getById(userCollection.getCollectionId());
            userCollectionDao.updateNumbering(userCollection.getId(), digitalCollection.getNumbering() + 1);
            digitalCollectionDao.updateNumbering(userCollection.getCollectionId());
        }
    }

    @Override
    public UserCollection getById(Long id) {
        return userCollectionDao.getById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void initAnti(DigitalCollection digitalCollection) {
        LambdaQueryWrapper<UserCollection> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserCollection::getCollectionId, digitalCollection.getId());
        wrapper.eq(UserCollection::getIsHold, true);
        wrapper.eq(UserCollection::getAntiHoardFlag, Boolean.FALSE);
        List<UserCollection> list = userCollectionDao.list(wrapper);
        if (CollUtil.isEmpty(list)) {
            return;
        }
        Map<Long, List<UserCollection>> collect = list.stream().collect(Collectors.groupingBy(UserCollection::getUserId));
        for (List<UserCollection> value : collect.values()) {
            int seqNo = 1;
            for (UserCollection userCollection : value.stream().sorted(Comparator.comparing(UserCollection::getId)).collect(Collectors.toList())) {
                userCollection.setHoardSeqNo(seqNo++);
                if (userCollection.getHoardSeqNo() > digitalCollection.getAntiHoardCount() && digitalCollection.getAntiHoardCount() > -1 && userCollection.getBuyPrice().compareTo(BigDecimal.ZERO) > 0 && digitalCollection.getAntiHoardRatio().compareTo(BigDecimal.ZERO) > 0) {
                    userCollection.setAntiHoardFlag(true);
                    userCollection.setAntiHoardPrice(userCollection.getBuyPrice().add(userCollection.getBuyPrice().multiply(digitalCollection.getAntiHoardRatio())));
                } else {
                    userCollection.setAntiHoardFlag(false);
                    userCollection.setAntiHoardPrice(BigDecimal.ZERO);
                }
                userCollection.updateById();
            }
        }

    }

    private void verifyOperBox(UserCollection userCollection, UserInfo userInfo) {
        verifyCollection(userCollection, userInfo);

        if (userCollection.getIsOpen()) {
            throw new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND);
        }
    }

    /**
     * 校验转增藏品
     *
     * @param userCollection
     * @param userInfo
     */
    private void verifyCollection(UserCollection userCollection, UserInfo userInfo) {

        if (ObjectUtil.isEmpty(userCollection)) {
            throw new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND);
        }

        if (userCollection.getUserId().longValue() != userInfo.getId().longValue()) {
            throw new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND);
        }

        if (!userCollection.getIsHold()) {
            throw new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND);
        }
        if (userCollection.getOnConsign() != CollectionOnConsignEnum.NORMAL) {
            throw new GlobalRunTimeException(ErrorCode.COLLECTION_ON_SIGN);
        }

        if (userCollection.getFreezingStatus() == UserCollectionFreezingStatusEnum.VERY_ACTIVE) {
            throw new GlobalRunTimeException("激活中的藏品不能转增");
        }
        if (userCollection.getFreezingStatus() == UserCollectionFreezingStatusEnum.PRESSING) {
            throw new GlobalRunTimeException("质押中的藏品不能转增");
        }
        if (userCollection.getFreezingStatus() == UserCollectionFreezingStatusEnum.LOCK) {
            throw new GlobalRunTimeException("锁定中的藏品不能转增");
        }


//        Assert.notNull(userCollection,()->new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND));
//        Assert.isFalse(userCollection.getUserId().longValue()==userInfo.getId().longValue(),()->new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND));
//        Assert.isTrue(userCollection.getIsHold(),()->new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND));
//        Assert.isTrue(userCollection.getIsOpen(),()->new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND));
    }

    @Override
    public List<ZhiTanUserHoldVO> userHold(Long userId, Integer page, Integer pageSize) {
        List<ZhiTanUserHoldVO> result = userCollectionDao.userHold(userId, page, pageSize);
        return result;
    }

    @Override
    public DaoIdentity getDaoIdentityName(Long daoId) {
        GetDaoByIdVO daoById = userCreatorInfoDao.getDaoById(daoId);
        if (ObjectUtil.isNull(daoById)) {
            throw new GlobalRunTimeException("该dao不存在！");
        }
        UserInfo user = UserPool.getUser();
        List<DaoIdentity> daoIdentities = daoIdentityDao.getByDaoId(daoId);
        //DAO没有配置身份卡就返回空
        if (CollUtil.isEmpty(daoIdentities)) {
            return new DaoIdentity();
        }
        Map<Integer, List<DaoIdentity>> levelMap = daoIdentities.stream().collect(Collectors.groupingBy(DaoIdentity::getLevel));
        //用户有身份卡就选取最高身份
        //根据身份卡的藏品idlist查用户是否持有身份卡
        List<UserCollection> userCollections = userCollectionDao.getByCollectionIdsAndUserId(daoIdentities.stream().map(DaoIdentity::getCollectionId).collect(Collectors.toList()), user.getId());
        if (CollUtil.isEmpty(userCollections)) {
            return new DaoIdentity();
        }
        //用户拥有的藏品id
        List<Long> collectionIdList = userCollections.stream().map(UserCollection::getCollectionId).collect(Collectors.toList());
        List<DaoIdentity> userHoldIdentity = daoIdentities.stream().filter(identity -> collectionIdList.contains(identity.getCollectionId())).collect(Collectors.toList());
        DaoIdentity maxIdentity = userHoldIdentity.stream().max(Comparator.comparing(DaoIdentity::getLevel)).get();
        //如果有多个等级一样高的身份卡，取最后获取的那个
        if (levelMap.get(maxIdentity.getLevel()).size() > 1) {
            List<DaoIdentity> sameLevelIdentityList = levelMap.get(maxIdentity.getLevel());
            userCollections.stream().sorted(Comparator.comparing(UserCollection::getId).reversed());
            //取最新的拥有的身份卡藏品（从最新的藏品开始判断是不是最高等级的身份卡）
            for (UserCollection userCollection : userCollections) {
                for (DaoIdentity daoIdentity : sameLevelIdentityList) {
                    userCollection.getCollectionId().equals(daoIdentity.getCollectionId());
                    return daoIdentity;
                }
            }
        }
        return maxIdentity;
    }

    @Override
    public HashMap oneClickImport(String userMobile, String userAddress, Integer page) {
        HashMap<String, Object> result = new HashMap<>();
        if (ObjectUtil.isNull(page)) {
            page = 1;
        }
        Integer pageSize = 10;
        UserInfo user = null;
        if (StrUtil.isNotBlank(userMobile)) {
            user = userInfoDao.getOneByUserTel(userMobile);
        } else {
            UserChainInfo byAddress = userChainInfoDao.getByAddress(userAddress);
            if (ObjectUtil.isNotNull(byAddress)) {
                user = userInfoDao.getById(byAddress.getUserId());
            }
        }

        if (ObjectUtil.isNull(user)) {
            result.put("err", Boolean.TRUE);
            result.put("msg", "用户不存在");
            return result;
        }
        Page<OneClickImportVO> data = userCollectionDao.oneClickImport(user.getId(), page, pageSize);
        result.put("err", Boolean.FALSE);
        result.put("data", data.getRecords());
        result.put("hasNext", data.hasNext());
        return result;
    }

    @Override
    public List<UserCollection> getCollectionIdByUserId(Long userId, List<Long> holdCollectionIds) {
        return userCollectionDao.getCollectionIdByUserId(userId, holdCollectionIds);
    }


    /**
     * 根据id查询
     *
     * @param userCollectionIdList
     * @return
     */
    @Override
    public List<UserCollection> getListByIdListAndDelete(List<Long> userCollectionIdList) {
        return userCollectionDao.getListByIdListAndDelete(userCollectionIdList);
    }

    /**
     * 我的版权藏品
     *
     * @param userId
     * @param pageNo
     * @param pageSize
     * @return
     */
    @Override
    public IPage<MyCopyrightCollectionNowVO> myCopyrightCollectionNow(Long userId, Integer pageNo, Integer pageSize) {
        Page<MyCopyrightCollectionNowVO> page = userCollectionDao.myCopyrightCollectionNow(userId, pageNo, pageSize);
        CopyrightAuctionConfig auctionConfig = copyrightAuctionConfigDao.getNewOne();
        page.getRecords().forEach(MyCopyrightCollectionNowVO -> {
            // 循环获取dao名字，dao的图片 藏品品质
            UserCreatorInfo byIdCash = userCreatorInfoDao.getByIdCash(MyCopyrightCollectionNowVO.getUserCreatorId());
            if (BeanUtil.isNotEmpty(byIdCash)) {
                MyCopyrightCollectionNowVO.setUserCreatorName(byIdCash.getDaoName());
                MyCopyrightCollectionNowVO.setUserCreatorImg(byIdCash.getCreatorAvatarImg());
            }
            ShowLevel byShowLevelCash = showLevelDao.getByShowLevelCash(MyCopyrightCollectionNowVO.getShowLevel());
            if (BeanUtil.isNotEmpty(byShowLevelCash)) {
                MyCopyrightCollectionNowVO.setShowLevelName(byShowLevelCash.getShowLevelName());
            }
            Integer count = copyrightAuctionRecordDao.getAfterTimeAndCollectionId(MyCopyrightCollectionNowVO.getCollectionId());
            if (null != count && count > 0) {
                MyCopyrightCollectionNowVO.setRegistration(Boolean.TRUE);
            }
            BigDecimal mapProsperity = nftRegionBindingService.getMapProsperity(MyCopyrightCollectionNowVO.getCollectionId());

            mapProsperity = auctionConfig.getProsperityRate().multiply(mapProsperity).setScale(1, RoundingMode.DOWN);
            //如果record.Prosperity 大于一万，则显示万元
            if (mapProsperity.compareTo(new BigDecimal("10000")) > 0) {
                mapProsperity = mapProsperity.divide(new BigDecimal("10000"), 1, RoundingMode.DOWN);
                MyCopyrightCollectionNowVO.setProsperity(mapProsperity + "万");
            } else {
                MyCopyrightCollectionNowVO.setProsperity(mapProsperity + "");
            }
            Date nftEffectiveTime = nftRegionBindingService.getNftEffectiveTime(MyCopyrightCollectionNowVO.getCollectionId());
            MyCopyrightCollectionNowVO.setEquityExpiryTime(nftEffectiveTime);
        });
        return page;
    }

    /**
     * 我的版权藏品详情
     *
     * @param id
     * @param id
     * @return
     */
    @Override
    public MyCopyrightCollectionDetailsVO myCopyrightCollectionDetails(UserInfo userInfo, Long id) {
        MyCopyrightCollectionDetailsVO collectionDetailsVO = new MyCopyrightCollectionDetailsVO();
        UserCollection userCollection = userCollectionDao.getById(id);
        collectionDetailsVO.setId(userCollection.getId());
        if (userCollection.getUserId().longValue() != UserPool.getUser().getId().longValue()) {
            throw new GlobalRunTimeException("非本人藏品");
        }
        collectionDetailsVO.setFreezingStatus(userCollection.getFreezingStatus());
        //藏品
        DigitalCollection digitalCollection = digitalCollectionDao.getById(userCollection.getCollectionId());
        collectionDetailsVO.setFirstTitle(digitalCollection.getFirstTitle());
        collectionDetailsVO.setProductDetailPicture(digitalCollection.getProductDetailPicture());
        collectionDetailsVO.setProductDetailPictureType(digitalCollection.getProductDetailPictureType());
        collectionDetailsVO.setProductPresentation(digitalCollection.getProductPresentation());
        collectionDetailsVO.setCreationContent(digitalCollection.getCreationContent());
        collectionDetailsVO.setModelImg(digitalCollection.getModelImg());
        collectionDetailsVO.setModelDistance(digitalCollection.getModelDistance());
        String privilegePresentation = digitalCollection.getPrivilegePresentation();
        if (ObjectUtil.isEmpty(privilegePresentation)) {
            privilegePresentation = "";
        }
        collectionDetailsVO.setPrivilegePresentation(privilegePresentation);
        collectionDetailsVO.setProductCount(digitalCollection.getSumCount());
        //作者
        UserCreatorInfo userCreatorInfo = userCreatorInfoDao.getById(digitalCollection.getUserCreatorId());
        collectionDetailsVO.setNickName(userCreatorInfo.getDaoName());
        collectionDetailsVO.setCreatorAvatarImg(userCreatorInfo.getCreatorAvatarImg());
        //系列
        CatenaInfo catenaInfo = catenaInfoDao.getById(digitalCollection.getCatenaId());
        collectionDetailsVO.setCatenaName(catenaInfo.getName());

        Integer circulationNum = userCollectionDao.getCirculationNumByCollectionId(digitalCollection.getId());

        Integer sumCount = digitalCollection.getSumCount();
        Integer sumCirculationNum = digitalCollection.getCirculationNum() + circulationNum;
        if (sumCount < sumCirculationNum) {
            sumCirculationNum = sumCount;
        }
        collectionDetailsVO.setCirculationNum(sumCirculationNum);
        collectionDetailsVO.setCirculationCount(digitalCollection.getCirculationCount());
        StaticData staticData = staticDataDao.getByType("purchase_notes");
        collectionDetailsVO.setPurchaseNotes(staticData.getValue());
        collectionDetailsVO.setThreeModelId(digitalCollection.getThreeModelId());
        collectionDetailsVO.setTopUpStatus(digitalCollection.getTopUpStatus());
        collectionDetailsVO.setChainStatus(0);
        collectionDetailsVO.setTianheChain("");
        //获取链信息
        CollectionChainDetailDTO collectionChainDetail = getCollectionChainDetail(userCollection);
        collectionDetailsVO.setTianheChain(collectionChainDetail.getTianheChain());
        collectionDetailsVO.setChainUrl(collectionChainDetail.getChainUrl());
        //collectionDetail.setContractAddress(collectionChainDetail.getContractAddress());
        Long between = 0L;
        Date createTime = userCollection.getCreateTime();
        if (ObjectUtil.isEmpty(createTime)) {
            createTime = userCollection.getModifyTime();
        }

        //交易确认中 :  allowConsign = false  isCancel = false isGive = false
        //按钮状态 1.可寄售: allowConsign = true  isCancel =false  isGive = false
        //按钮状态 2.取消: allowConsign = false  isCancel =true  isGive = false
        //按钮状态 2.可转增: allowConsign = false  isCancel =false  isGive = true
        Boolean isGive = Boolean.FALSE;
        Boolean isTrade = Boolean.FALSE;
        //查询当前藏品在二级的配置
//        SecondCollectionConfig secondCollectionConfig = secondCollectionConfigDao.getByCollectionIdAndStatus(userCollection.getCollectionId());
//        SecondCollection secondCollection = secondCollectionDao.getOnShelfUserCollectionId(userCollection.getId());
//        collectionDetailsVO.setMarketType(BeanUtil.isNotEmpty(secondCollectionConfig)?secondCollectionConfig.getMarketType():null);
        //如果当前藏品在二级上架 就是可取消状态
        if (userCollection.getStatus() != ChainStatusEnum.ONLINE) {
            isTrade = Boolean.TRUE;
        }
        collectionDetailsVO.setIsTrade(isTrade);
        collectionDetailsVO.setIsGive(isGive);

        collectionDetailsVO.setCollectionId(digitalCollection.getId());
        collectionDetailsVO.setCountdown(between);
        collectionDetailsVO.setNumbering(userCollection.getNumbering() + "/" + digitalCollection.getSumCount());
        collectionDetailsVO.setSkipUrl(digitalCollection.getSkipUrl());
        collectionDetailsVO.setContractAddress(collectionChainDetail.getContractAddress());
        collectionDetailsVO.setLockedPositionTime(userCollection.getLockedPositionTime());
        collectionDetailsVO.setIsSmeltingOnly(userCollection.getIsSmeltingOnly());
        //先查询权益是否生效中
        Date nftEffectiveTime = nftRegionBindingService.getNftEffectiveTime(userCollection.getCollectionId());
        Boolean equityInEffect = Boolean.FALSE;
        if (Objects.nonNull(nftEffectiveTime) && nftEffectiveTime.after(new Date())) {
            equityInEffect = Boolean.TRUE;
        }
        if (equityInEffect) {
            collectionDetailsVO.setButtonStatus(CopyrightCollectionDetailsAuctionStatusEnum.EQUITY_IN_EFFECT);
        } else {
            CopyrightAuction copyrightAuction = copyrightAuctionDao.getByCollectionId(userCollection.getCollectionId());
            if (Objects.isNull(copyrightAuction) || !copyrightAuction.getStatus()) {
                collectionDetailsVO.setButtonStatus(CopyrightCollectionDetailsAuctionStatusEnum.EQUITY_NOT_IN_EFFECT);
                return collectionDetailsVO;
            }
            CopyrightAuctionConfig copyrightAuctionConfig = copyrightAuctionConfigDao.getNewOne();
            //查询今日是否有拍卖
            CopyrightAuctionRecord todayRecode = copyrightAuctionRecordDao.getByCollectionAndToday(userCollection.getCollectionId());
            //明天拍卖的记录
            CopyrightAuctionRecord nextDayRecord = copyrightAuctionRecordDao.getByCollectionAndTomorrow(userCollection.getCollectionId());
            //每日开始时间 格式是HH:mm:ss
            Date auctionStartTime = copyrightAuctionConfig.getAuctionStartTime();
            //每日结束时间 格式是HH:mm:ss
            Date auctionEndTime = copyrightAuctionConfig.getAuctionEndTime();
            //将每日开始时间和结束时间转成今日yyyy-MM-dd HH:mm:ss格式的
            Date date = new Date();
            String today = DateUtil.format(date, "yyyy-MM-dd");
            String startTime = today + " " + DateUtil.format(auctionStartTime, "HH:mm:ss");
            DateTime todayStartTime = DateUtil.parse(startTime);

            String endTime = today + " " + DateUtil.format(auctionEndTime, "HH:mm:ss");
            DateTime todayEndTime = DateUtil.parse(endTime);

            //今天时间 -1小时
            DateTime dateTime = DateUtil.offsetHour(todayStartTime, -1);
            //今天没拍卖
            if (Objects.isNull(todayRecode) || todayRecode.getHaveResult()) {
                //判断当前时间是否是每日开始时间之前1小时
                if (date.before(dateTime)) {
                    collectionDetailsVO.setButtonStatus(CopyrightCollectionDetailsAuctionStatusEnum.REGISTRATION);
                } else {
                    //明天存在记录就是修改、不存在就是报名拍卖
                    if (Objects.nonNull(nextDayRecord)) {
                        collectionDetailsVO.setButtonStatus(CopyrightCollectionDetailsAuctionStatusEnum.UPDATE_START_PRICE);
                    } else {
                        collectionDetailsVO.setButtonStatus(CopyrightCollectionDetailsAuctionStatusEnum.REGISTRATION);
                    }
                }
            } else {
                collectionDetailsVO.setButtonStatus(CopyrightCollectionDetailsAuctionStatusEnum.UPDATE_START_PRICE);
                if (DateUtil.isIn(date, todayRecode.getAuctionStartTime(), todayRecode.getAuctionEndTime())) {
                    collectionDetailsVO.setButtonStatus(CopyrightCollectionDetailsAuctionStatusEnum.AUCTION_IS_UNDERWAY);
                }
            }
            if (collectionDetailsVO.getButtonStatus() == null) {
                collectionDetailsVO.setButtonStatus(CopyrightCollectionDetailsAuctionStatusEnum.EQUITY_NOT_IN_EFFECT);
            }
        }
        return collectionDetailsVO;
    }

    /**
     * 拍卖成功
     *
     * @param userCollectionId
     * @param toUserId
     * @return
     */
    @Override
    public void successfulAuction(Long userCollectionId, Long toUserId) {
        UserCollection userCollection = userCollectionDao.getById(userCollectionId);
        if (ObjectUtil.isEmpty(userCollection)) {
            throw new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND);
        }
        if (!userCollection.getIsHold()) {
            throw new GlobalRunTimeException(ErrorCode.COLLECTION_NOT_FOUND);
        }

        userCollection.setGiveTime(DateTime.now());
        userCollection.setIsHold(false);
        userCollection.setToUserId(toUserId);
        if (!userCollection.updateById()) {
            throw new GlobalRunTimeException(ErrorCode.THE_SYSTEM_IS_BUSY_PLEASE_TRY_AGAIN_LATER);
        }
        // 给拍卖成功用户藏品
        UserCollection buyUserCollection = addCollection(toUserId, userCollection.getUserId(), userCollection.getCollectionId(),
                userCollection.getCollectionUuid(), userCollection.getCollectionImage(), userCollection.getLevel(), userCollection.getFirstTitle(),
                userCollection.getUserCreatorId(), ReceivedCollectionType.AUCTION, userCollection.getBoxId(), userCollection.getBoxTitle(),
                userCollection.getBoxImage(), userCollection.getIsOpen(), userCollection.getProductId(), userCollection.getOrderId(), 0L, BigDecimal.ZERO, userCollection.getNumbering(), userCollection.getId(), userCollection.getChainUrl(), AddCollectionEnum.DEFAULT, null, null, false);

        //藏品流转表记录
        CollectionCirculatingRecord collectionCirculatingRecord = new CollectionCirculatingRecord();
        collectionCirculatingRecord.setUserId(userCollection.getUserId());
        collectionCirculatingRecord.setCollectionId(userCollection.getCollectionId());
        collectionCirculatingRecord.setReceivedCollectionType(ReceivedCollectionType.AUCTION);
        collectionCirculatingRecord.setTypeClassify(ClassifyType.COLLECTION);
        collectionCirculatingRecord.setToUserCollection(buyUserCollection.getId());
        collectionCirculatingRecord.setToUserId(buyUserCollection.getUserId());
        collectionCirculatingRecord.setFromUserId(userCollection.getUserId());
        collectionCirculatingRecord.setFromUserCollection(userCollection.getId());
        collectionCirculatingRecord.insert();

        CollectionCirculatingRecord fromCollectionCirculatingRecord = new CollectionCirculatingRecord();
        fromCollectionCirculatingRecord.setUserId(userCollection.getUserId());
        fromCollectionCirculatingRecord.setCollectionId(userCollection.getCollectionId());
        fromCollectionCirculatingRecord.setReceivedCollectionType(ReceivedCollectionType.AUCTION);
        fromCollectionCirculatingRecord.setTypeClassify(ClassifyType.COLLECTION);
        fromCollectionCirculatingRecord.setToUserCollection(buyUserCollection.getId());
        fromCollectionCirculatingRecord.setToUserId(buyUserCollection.getUserId());
        fromCollectionCirculatingRecord.setFromUserId(userCollection.getUserId());
        fromCollectionCirculatingRecord.setFromUserCollection(userCollection.getId());
        fromCollectionCirculatingRecord.insert();
    }

    @Override
    public UserCollection getUserByCollectionIdOne(Long userId, Long collectionId) {
        return userCollectionDao.getUserByCollectionIdOne(userId, collectionId);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void recoverTradingPoolCollection(UserCollection userCollection) {
        UserChainInfo userChainInfo = userChainInfoDao.getRegisterByUserId(1L);
        //标记藏品为回收状态 并且当前用户未持有
        Assert.isTrue(userCollectionDao.recoverCollectionById(userCollection.getId(), userChainInfo.getUserId()), () -> new GlobalRunTimeException(ErrorCode.THE_SYSTEM_IS_BUSY_PLEASE_TRY_AGAIN_LATER));
        privilegeService.flushUserLevel(userCollection.getUserId());
        //降级逻辑
        daoService.downgrade(userCollection.getCollectionId(), userCollection.getUserId(), ReceivedCollectionType.GIVE);


        UserCollectionChainLog formUserChainLogInfo = userCollectionChainLogDao.getOneByUserIdAndUserCollectionId(userCollection.getUserId(), userCollection.getId());

        UserCollectionChainLog userCollectionChainLog = new UserCollectionChainLog();
        userCollectionChainLog.setUserId(userCollection.getUserId());
        userCollectionChainLog.setDaoId(0L);
        userCollectionChainLog.setUserCollectionId(userCollection.getId());
        userCollectionChainLog.setCollectionType(ReceivedCollectionType.RECYCLE);
        userCollectionChainLog.setType(UserChainTypeEnum.RECYCLE);
        userCollectionChainLog.setStatus(UserChainLogStatusEnum.WAIT);
        userCollectionChainLog.setCollectionId(userCollection.getCollectionId());
        userCollectionChainLog.setContractAddress(formUserChainLogInfo.getContractAddress());
        userCollectionChainLog.setDeployTransactionHash(formUserChainLogInfo.getTransactionHash());
        userCollectionChainLog.setProductId(formUserChainLogInfo.getProductId());
        userCollectionChainLog.setAddress(formUserChainLogInfo.getAddress());
        userCollectionChainLog.setTokenId(formUserChainLogInfo.getTokenId());
        userCollectionChainLog.setFromUserId(userCollection.getUserId());
        userCollectionChainLog.setFromUserCollectionId(userCollection.getId());
        userCollectionChainLog.setFromUserAddress(formUserChainLogInfo.getToUserAddress());
        userCollectionChainLog.setToUserId(1L);
        userCollectionChainLog.setToUserCollectionId(0L);
        userCollectionChainLog.setToUserAddress(userChainInfo.getAddress());
        userCollectionChainLog.setCollectionChainId(0L);
        userCollectionChainLog.insert();

        // 增加一条记录,用来记录链回收的日志,来把用户的藏品给回收回来.收回来以后.在回调的时候,去验证这里面的数据,存不存在 如果存在的话把对应的collection的库存在-1 因为他本身不该+1的.
        TradingRecycleLog tradingRecycleLog = new TradingRecycleLog();
        tradingRecycleLog.setUserCollectionChainLogId(userCollectionChainLog.getId());
        tradingRecycleLog.setUserCollectionId(userCollection.getId());
        tradingRecycleLog.setUserId(userCollection.getUserId());
        boolean save = tradingRecycleLogDao.save(tradingRecycleLog);
        if (!save) {
            throw new GlobalRunTimeException("回收失败");
        }
    }
}
